瀏覽代碼

优化数据库 与 简化控制器 & more

1. 继续修改表表关系,与关联字段的限制;
2. 通过表表关系,简化一部分代码,自动让Laravel建立关联;
3. 拆分验证 与 优化数据创建与修改的获取数据操作;
4. 修改部分无意义的数据名称;
兔姬桑 4 年之前
父節點
當前提交
f25f2aea62
共有 100 個文件被更改,包括 1708 次插入1837 次删除
  1. 30 18
      app/Console/Commands/AutoClearLog.php
  2. 1 5
      app/Console/Commands/AutoJob.php
  3. 2 0
      app/Exceptions/Handler.php
  4. 16 31
      app/Http/Controllers/Admin/AffiliateController.php
  5. 23 38
      app/Http/Controllers/Admin/ArticleController.php
  6. 26 38
      app/Http/Controllers/Admin/CertController.php
  7. 1 3
      app/Http/Controllers/Admin/Config/EmailFilterController.php
  8. 4 5
      app/Http/Controllers/Admin/Config/LabelController.php
  9. 10 19
      app/Http/Controllers/Admin/CouponController.php
  10. 27 57
      app/Http/Controllers/Admin/LogsController.php
  11. 2 6
      app/Http/Controllers/Admin/MarketingController.php
  12. 62 0
      app/Http/Controllers/Admin/NodeAuthController.php
  13. 31 108
      app/Http/Controllers/Admin/NodeController.php
  14. 9 25
      app/Http/Controllers/Admin/PermissionController.php
  15. 18 34
      app/Http/Controllers/Admin/RoleController.php
  16. 15 42
      app/Http/Controllers/Admin/RuleController.php
  17. 23 102
      app/Http/Controllers/Admin/RuleGroupController.php
  18. 13 24
      app/Http/Controllers/Admin/ShopController.php
  19. 4 14
      app/Http/Controllers/Admin/SubscribeController.php
  20. 1 4
      app/Http/Controllers/Admin/SystemController.php
  21. 11 23
      app/Http/Controllers/Admin/TicketController.php
  22. 2 7
      app/Http/Controllers/Admin/ToolsController.php
  23. 31 48
      app/Http/Controllers/Admin/UserController.php
  24. 23 44
      app/Http/Controllers/Admin/UserGroupController.php
  25. 40 53
      app/Http/Controllers/AdminController.php
  26. 1 1
      app/Http/Controllers/Api/Client/V1Controller.php
  27. 14 24
      app/Http/Controllers/Api/WebApi/BaseController.php
  28. 4 9
      app/Http/Controllers/Api/WebApi/TrojanController.php
  29. 11 30
      app/Http/Controllers/Api/WebApi/V2RayController.php
  30. 4 10
      app/Http/Controllers/Api/WebApi/VNetController.php
  31. 18 34
      app/Http/Controllers/AuthController.php
  32. 25 31
      app/Http/Controllers/PaymentController.php
  33. 11 10
      app/Http/Controllers/User/AffiliateController.php
  34. 1 1
      app/Http/Controllers/User/SubscribeController.php
  35. 87 115
      app/Http/Controllers/UserController.php
  36. 5 5
      app/Http/Requests/Admin/ArticleRequest.php
  37. 17 0
      app/Http/Requests/Admin/CertRequest.php
  38. 5 4
      app/Http/Requests/Admin/CouponRequest.php
  39. 16 0
      app/Http/Requests/Admin/PermissionRequest.php
  40. 16 0
      app/Http/Requests/Admin/RbacRequest.php
  41. 17 0
      app/Http/Requests/Admin/RoleRequest.php
  42. 17 0
      app/Http/Requests/Admin/RuleGroupRequest.php
  43. 17 0
      app/Http/Requests/Admin/RuleRequest.php
  44. 16 0
      app/Http/Requests/Admin/UserGroupRequest.php
  45. 12 1
      app/Models/Coupon.php
  46. 2 2
      app/Models/Label.php
  47. 13 20
      app/Models/Node.php
  48. 2 2
      app/Models/NodeHeartBeat.php
  49. 0 25
      app/Models/NodeLabel.php
  50. 2 2
      app/Models/NodeOnlineIp.php
  51. 1 1
      app/Models/NodeOnlineLog.php
  52. 0 13
      app/Models/NodeRule.php
  53. 5 5
      app/Models/Order.php
  54. 5 0
      app/Models/ReferralApply.php
  55. 5 0
      app/Models/Rule.php
  56. 6 2
      app/Models/RuleGroup.php
  57. 0 13
      app/Models/RuleGroupNode.php
  58. 7 1
      app/Models/Ticket.php
  59. 10 19
      app/Models/User.php
  60. 11 2
      app/Models/UserGroup.php
  61. 1 1
      app/Models/UserSubscribe.php
  62. 0 34
      app/Observers/RuleGroupObserver.php
  63. 3 3
      app/Observers/UserObserver.php
  64. 0 2
      app/Providers/AppServiceProvider.php
  65. 0 17
      app/Services/NodeService.php
  66. 274 150
      composer.lock
  67. 1 1
      config/version.php
  68. 8 1
      database/factories/UserFactory.php
  69. 192 0
      database/migrations/2020_12_24_074739_table_improvement.php
  70. 4 1
      database/seeds/DatabaseSeeder.php
  71. 106 123
      database/seeds/PresetSeeder.php
  72. 0 0
      public/downloads/convert.json
  73. 3 3
      resources/views/admin/aff/detail.blade.php
  74. 25 6
      resources/views/admin/aff/index.blade.php
  75. 15 15
      resources/views/admin/aff/rebate.blade.php
  76. 1 1
      resources/views/admin/article/edit.blade.php
  77. 1 1
      resources/views/admin/article/index.blade.php
  78. 5 5
      resources/views/admin/config/config.blade.php
  79. 31 24
      resources/views/admin/coupon/create.blade.php
  80. 1 1
      resources/views/admin/coupon/index.blade.php
  81. 13 0
      resources/views/admin/index.blade.php
  82. 11 11
      resources/views/admin/logs/callback.blade.php
  83. 12 12
      resources/views/admin/logs/notification.blade.php
  84. 13 13
      resources/views/admin/logs/onlineIPMonitor.blade.php
  85. 3 3
      resources/views/admin/logs/order.blade.php
  86. 14 14
      resources/views/admin/logs/traffic.blade.php
  87. 11 11
      resources/views/admin/logs/userBanHistory.blade.php
  88. 12 12
      resources/views/admin/logs/userCreditHistory.blade.php
  89. 14 14
      resources/views/admin/logs/userTraffic.blade.php
  90. 9 9
      resources/views/admin/marketing/emailList.blade.php
  91. 9 9
      resources/views/admin/marketing/pushList.blade.php
  92. 30 30
      resources/views/admin/node/auth.blade.php
  93. 12 12
      resources/views/admin/node/cert/index.blade.php
  94. 24 28
      resources/views/admin/node/cert/info.blade.php
  95. 21 9
      resources/views/admin/node/info.blade.php
  96. 10 8
      resources/views/admin/permission/info.blade.php
  97. 2 2
      resources/views/admin/role/info.blade.php
  98. 0 107
      resources/views/admin/rule/group/assign.blade.php
  99. 6 11
      resources/views/admin/rule/group/index.blade.php
  100. 3 3
      resources/views/admin/rule/group/info.blade.php

+ 30 - 18
app/Console/Commands/AutoClearLog.php

@@ -5,8 +5,11 @@ namespace App\Console\Commands;
 use App\Models\NodeDailyDataFlow;
 use App\Models\NodeHeartBeat;
 use App\Models\NodeHourlyDataFlow;
+use App\Models\NodeOnlineIp;
 use App\Models\NodeOnlineLog;
-use App\Models\NodeOnlineUserIp;
+use App\Models\NotificationLog;
+use App\Models\Payment;
+use App\Models\RuleLog;
 use App\Models\UserBanedLog;
 use App\Models\UserDailyDataFlow;
 use App\Models\UserDataFlowLog;
@@ -41,17 +44,32 @@ class AutoClearLog extends Command
     private function clearLog(): void
     {
         try {
+            // 清除节点每天流量数据日志
+            NodeDailyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-2 month')))->delete();
+
+            // 清除节点每小时流量数据日志
+            NodeHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete();
+
+            // 清理通知日志
+            NotificationLog::where('updated_at', '<=', date('Y-m-d H:i:s', strtotime('-1 month')))->delete();
+
             // 清除节点负载信息日志
             NodeHeartBeat::where('log_time', '<=', strtotime('-30 minutes'))->delete();
 
             // 清除节点在线用户数日志
             NodeOnlineLog::where('log_time', '<=', strtotime('-1 hour'))->delete();
 
-            // 清除用户流量日志
-            UserDataFlowLog::where('log_time', '<=', strtotime('-3 days'))->delete();
+            // 清理在线支付日志
+            Payment::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-1 year')))->delete();
 
-            // 清除用户每时各流量数据日志
-            UserHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete();
+            // 清理审计触发日志
+            RuleLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete();
+
+            // 清除用户连接IP
+            NodeOnlineIp::where('created_at', '<=', strtotime('-1 week'))->delete();
+
+            // 清除用户封禁日志
+            UserBanedLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete();
 
             // 清除用户各节点 / 节点总计的每天流量数据日志
             UserDailyDataFlow::where('node_id', '<>', null)
@@ -59,23 +77,17 @@ class AutoClearLog extends Command
                 ->orWhere('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))
                 ->delete();
 
-            // 清除节点每小时流量数据日志
-            NodeHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete();
-
-            // 清除节点每天流量数据日志
-            NodeDailyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-2 month')))->delete();
-
-            // 清除用户封禁日志
-            UserBanedLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete();
-
-            // 清除用户连接IP
-            NodeOnlineUserIp::where('created_at', '<=', strtotime('-1 month'))->delete();
+            // 清除用户每时各流量数据日志
+            UserHourlyDataFlow::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 days')))->delete();
 
             // 清除用户登陆日志
-            UserLoginLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete();
+            UserLoginLog::where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-3 month')))->delete(); // 清除用户订阅记录
 
-            // 清除用户订阅记录
+            // 清理用户订阅请求日志
             UserSubscribeLog::where('request_time', '<=', date('Y-m-d H:i:s', strtotime('-1 month')))->delete();
+
+            // 清除用户流量日志
+            UserDataFlowLog::where('log_time', '<=', strtotime('-3 days'))->delete();
         } catch (Exception $e) {
             Log::error('【清理日志】错误: '.$e->getMessage());
         }

+ 1 - 5
app/Console/Commands/AutoJob.php

@@ -80,11 +80,7 @@ class AutoJob extends Command
         VerifyCode::recentUnused()->update(['status' => 2]);
 
         // 优惠券到期 / 用尽的 自动置无效
-        Coupon::whereStatus(0)
-            ->where('end_time', '<=', time())
-            ->orWhereIn('type', [1, 2])
-            ->whereUsableTimes(0)
-            ->update(['status' => 2]);
+        Coupon::withTrashed()->whereStatus(0)->where('end_time', '<=', time())->orWhereIn('type', [1, 2])->whereUsableTimes(0)->update(['status' => 2]);
 
         // 邀请码到期自动置无效
         Invite::whereStatus(0)->where('dateline', '<=', date('Y-m-d H:i:s'))->update(['status' => 2]);

+ 2 - 0
app/Exceptions/Handler.php

@@ -9,6 +9,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
 use Illuminate\Http\Client\ConnectionException;
 use Illuminate\Http\Request;
 use Illuminate\Session\TokenMismatchException;
+use Illuminate\Validation\ValidationException;
 use Log;
 use ReflectionException;
 use Response;
@@ -25,6 +26,7 @@ class Handler extends ExceptionHandler
      */
     protected $dontReport = [
         HttpException::class,
+        ValidationException::class,
     ];
 
     /**

+ 16 - 31
app/Http/Controllers/Admin/AffiliateController.php

@@ -5,15 +5,8 @@ namespace App\Http\Controllers\Admin;
 use App\Http\Controllers\Controller;
 use App\Models\ReferralApply;
 use App\Models\ReferralLog;
-use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
-use Response;
 
-/**
- * 推广控制器.
- *
- * Class AffiliateController
- */
 class AffiliateController extends Controller
 {
     // 提现申请列表
@@ -33,44 +26,38 @@ class AffiliateController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['applyList'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.aff.index', $view);
+        return view('admin.aff.index', ['applyList' => $query->latest()->paginate(15)->appends($request->except('page'))]);
     }
 
     // 提现申请详情
-    public function detail(Request $request, $id)
+    public function detail(Request $request, ReferralApply $aff)
     {
-        $view['basic'] = ReferralApply::with('user:id,email')->find($id);
-        $view['commissions'] = [];
-        if ($view['basic'] && $view['basic']->link_logs) {
-            $view['commissions'] = ReferralLog::with(['invitee:id,email', 'order.goods:id,name'])
-                ->whereIn('id', $view['basic']->link_logs)
+        if ($aff->link_logs) {
+            $commissions = ReferralLog::with(['invitee:id,email', 'order.goods:id,name'])
+                ->whereIn('id', $aff->link_logs)
                 ->paginate(15)
                 ->appends($request->except('page'));
         }
 
-        return view('admin.aff.detail', $view);
+        return view('admin.aff.detail', [
+            'referral' => $aff->load('user:id,email'),
+            'commissions' => $commissions ?? null,
+        ]);
     }
 
     // 设置提现申请状态
-    public function setStatus(Request $request): JsonResponse
+    public function setStatus(Request $request, ReferralApply $aff)
     {
-        $id = $request->input('id');
-        $status = (int) $request->input('status');
+        $status = (int) $request->validate(['status' => 'required|numeric|between:-1,2']);
 
-        $ret = ReferralApply::whereId($id)->update(['status' => $status]);
-        if ($ret) {
+        if ($aff->update(['status' => $status])) {
             // 审核申请的时候将关联的
-            $referralApply = ReferralApply::findOrFail($id);
-            if ($referralApply && $status === 1) {
-                ReferralLog::whereIn('id', $referralApply->link_logs)->update(['status' => 1]);
-            } elseif ($referralApply && $status === 2) {
-                ReferralLog::whereIn('id', $referralApply->link_logs)->update(['status' => 2]);
+            if ($status === 1 || $status === 2) {
+                $aff->referral_logs()->update(['status' => $status]);
             }
         }
 
-        return Response::json(['status' => 'success', 'message' => '操作成功']);
+        return response()->json(['status' => 'success', 'message' => '操作成功']);
     }
 
     // 用户返利流水记录
@@ -98,8 +85,6 @@ class AffiliateController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['list'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.aff.rebate', $view);
+        return view('admin.aff.rebate', ['referralLogs' => $query->paginate(15)->appends($request->except('page'))]);
     }
 }

+ 23 - 38
app/Http/Controllers/Admin/ArticleController.php

@@ -6,22 +6,15 @@ use App\Http\Controllers\Controller;
 use App\Http\Requests\Admin\ArticleRequest;
 use App\Models\Article;
 use Exception;
-use Illuminate\Http\JsonResponse;
-use Illuminate\Http\RedirectResponse;
-use Illuminate\Http\Request;
 use Illuminate\Http\UploadedFile;
 use Log;
-use Redirect;
-use Response;
 
 class ArticleController extends Controller
 {
     // 文章列表
-    public function index(Request $request)
+    public function index()
     {
-        $view['articles'] = Article::orderByDesc('sort')->paginate(15)->appends($request->except('page'));
-
-        return view('admin.article.index', $view);
+        return view('admin.article.index', ['articles' => Article::orderByDesc('sort')->paginate(15)->appends(request('page'))]);
     }
 
     // 添加文章页面
@@ -33,9 +26,9 @@ class ArticleController extends Controller
     // 添加文章
     public function store(ArticleRequest $request)
     {
-        $data = $request->except('_method', '_token');
+        $data = $request->validated();
         // LOGO
-        if ($request->input('type') !== '4' && $request->hasFile('logo')) {
+        if ($data['type'] !== '4' && $request->hasFile('logo')) {
             $path = $this->fileUpload($request->file('logo'));
             if (is_string($path)) {
                 $data['logo'] = $path;
@@ -44,50 +37,44 @@ class ArticleController extends Controller
             }
         }
 
-        $article = Article::create($data);
-        if ($article->id) {
-            return Redirect::route('admin.article.edit', $article->id)->with('successMsg', '添加成功');
+        if ($article = Article::create($data)) {
+            return redirect(route('admin.article.edit', $article))->with('successMsg', '添加成功');
         }
 
-        return Redirect::back()->withInput()->withErrors('添加失败');
+        return redirect()->back()->withInput()->withErrors('添加失败');
     }
 
     // 图片上传
     public function fileUpload(UploadedFile $file)
     {
         $fileName = Str::random(8).time().'.'.$file->getClientOriginalExtension();
-        $path = $file->storeAs('public', $fileName);
 
-        if (! $path) {
-            return Redirect::back()->withInput()->withErrors('Logo存储失败');
+        if (! $file->storeAs('public', $fileName)) {
+            return redirect()->back()->withInput()->withErrors('Logo存储失败');
         }
 
         return 'upload/'.$fileName;
     }
 
     // 文章页面
-    public function show($id)
+    public function show(Article $article)
     {
-        $view['article'] = Article::find($id);
-
-        return view('admin.article.show', $view);
+        return view('admin.article.show', compact('article'));
     }
 
     // 编辑文章页面
-    public function edit($id)
+    public function edit(Article $article)
     {
-        $view['article'] = Article::find($id);
-
-        return view('admin.article.edit', $view);
+        return view('admin.article.edit', compact('article'));
     }
 
     // 编辑文章
-    public function update(ArticleRequest $request, $id): RedirectResponse
+    public function update(ArticleRequest $request, Article $article)
     {
-        $data = $request->except('_method', '_token');
+        $data = $request->validated();
         $data['logo'] = $data['logo'] ?? null;
         // LOGO
-        if ($request->input('type') != 4 && $request->hasFile('logo')) {
+        if ($data['type'] !== '4' && $request->hasFile('logo')) {
             $path = $this->fileUpload($request->file('logo'));
             if (is_string($path)) {
                 $data['logo'] = $path;
@@ -96,26 +83,24 @@ class ArticleController extends Controller
             }
         }
 
-        if (Article::find($id)->update($data)) {
-            return Redirect::back()->with('successMsg', '编辑成功');
+        if ($article->update($data)) {
+            return redirect()->back()->with('successMsg', '编辑成功');
         }
 
-        return Redirect::back()->withErrors('编辑失败');
+        return redirect()->back()->withInput()->withErrors('编辑失败');
     }
 
     // 删除文章
-    public function destroy($id): JsonResponse
+    public function destroy(Article $article)
     {
         try {
-            Article::find($id)->delete();
+            $article->delete();
         } catch (Exception $e) {
             Log::error('删除文章失败:'.$e->getMessage());
 
-            return Response::json(
-                ['status' => 'fail', 'message' => '删除失败:'.$e->getMessage()]
-            );
+            return response()->json(['status' => 'fail', 'message' => '删除失败:'.$e->getMessage()]);
         }
 
-        return Response::json(['status' => 'success', 'message' => '删除成功']);
+        return response()->json(['status' => 'success', 'message' => '删除成功']);
     }
 }

+ 26 - 38
app/Http/Controllers/Admin/CertController.php

@@ -3,32 +3,29 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
+use App\Http\Requests\Admin\CertRequest;
 use App\Models\NodeCertificate;
 use Exception;
-use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Request;
 use Log;
-use Response;
 
 class CertController extends Controller
 {
     // 域名证书列表
-    public function index(Request $request)
+    public function index()
     {
-        $DvList = NodeCertificate::orderBy('id')->paginate(15)->appends($request->except('page'));
-        foreach ($DvList as $Dv) {
-            if ($Dv->pem) {
-                $DvInfo = openssl_x509_parse($Dv->pem);
-                if ($DvInfo) {
-                    $Dv->issuer = $DvInfo['issuer']['O'] ?? null;
-                    $Dv->from = date('Y-m-d', $DvInfo['validFrom_time_t']) ?: null;
-                    $Dv->to = date('Y-m-d', $DvInfo['validTo_time_t']) ?: null;
+        $certs = NodeCertificate::orderBy('id')->paginate(15)->appends(request('page'));
+        foreach ($certs as $cert) {
+            if ($cert->pem) {
+                $certInfo = openssl_x509_parse($cert->pem);
+                if ($certInfo) {
+                    $cert->issuer = $certInfo['issuer']['O'] ?? null;
+                    $cert->from = date('Y-m-d', $certInfo['validFrom_time_t']) ?: null;
+                    $cert->to = date('Y-m-d', $certInfo['validTo_time_t']) ?: null;
                 }
             }
         }
-        $view['list'] = $DvList;
 
-        return view('admin.node.cert.index', $view);
+        return view('admin.node.cert.index', ['certs' => $certs]);
     }
 
     public function create()
@@ -37,52 +34,43 @@ class CertController extends Controller
     }
 
     // 添加域名证书
-    public function store(Request $request): JsonResponse
+    public function store(CertRequest $request)
     {
-        $cert = new NodeCertificate();
-        $cert->domain = $request->input('domain');
-        $cert->key = str_replace(["\r", "\n"], '', $request->input('key'));
-        $cert->pem = str_replace(["\r", "\n"], '', $request->input('pem'));
-        $cert->save();
-
-        if ($cert->id) {
-            return Response::json(['status' => 'success', 'message' => '生成成功']);
+        if ($cert = NodeCertificate::create($request->validated())) {
+            return redirect(route('admin.node.cert.update', $cert))->with('successMsg', '生成成功');
         }
 
-        return Response::json(['status' => 'fail', 'message' => '生成失败']);
+        return redirect()->back()->withInput()->withErrors('生成失败');
     }
 
     // 编辑域名证书
-    public function edit($id)
+    public function edit(NodeCertificate $cert)
     {
-        $view['Dv'] = NodeCertificate::find($id);
-
-        return view('admin.node.cert.info', $view);
+        return view('admin.node.cert.info', compact('cert'));
     }
 
-    public function update(Request $request, $id): JsonResponse
+    public function update(CertRequest $request, NodeCertificate $cert)
     {
-        $Dv = NodeCertificate::findOrFail($id);
-        if ($Dv->update(['domain' => $request->input('domain'), 'key' => $request->input('key'), 'pem' => $request->input('pem')])) {
-            return Response::json(['status' => 'success', 'message' => '修改成功']);
+        if ($cert->update($request->validated())) {
+            return redirect()->back()->with('successMsg', '修改成功');
         }
 
-        return Response::json(['status' => 'fail', 'message' => '修改失败']);
+        return redirect()->back()->withInput()->withErrors('修改失败');
     }
 
     // 删除域名证书
-    public function destroy($id): JsonResponse
+    public function destroy(NodeCertificate $cert)
     {
         try {
-            if (NodeCertificate::whereId($id)->delete()) {
-                return Response::json(['status' => 'success', 'message' => '操作成功']);
+            if ($cert->delete()) {
+                return response()->json(['status' => 'success', 'message' => '操作成功']);
             }
         } catch (Exception $e) {
             Log::error('删除域名证书失败:'.$e->getMessage());
 
-            return Response::json(['status' => 'fail', 'message' => '删除域名证书失败:'.$e->getMessage()]);
+            return response()->json(['status' => 'fail', 'message' => '删除域名证书错误:'.$e->getMessage()]);
         }
 
-        return Response::json(['status' => 'fail', 'message' => '删除域名证书失败']);
+        return response()->json(['status' => 'fail', 'message' => '删除域名证书失败']);
     }
 }

+ 1 - 3
app/Http/Controllers/Admin/Config/EmailFilterController.php

@@ -16,9 +16,7 @@ class EmailFilterController extends Controller
     // 邮箱过滤列表
     public function index()
     {
-        $view['list'] = EmailFilter::orderByDesc('id')->paginate(15);
-
-        return view('admin.config.emailFilter', $view);
+        return view('admin.config.emailFilter', ['list' => EmailFilter::orderByDesc('id')->paginate()]);
     }
 
     // 添加邮箱后缀

+ 4 - 5
app/Http/Controllers/Admin/Config/LabelController.php

@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin\Config;
 
 use App\Http\Controllers\Controller;
 use App\Models\Label;
-use App\Models\NodeLabel;
 use Exception;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
@@ -28,9 +27,9 @@ class LabelController extends Controller
     }
 
     // 编辑标签
-    public function update(Request $request, $id): JsonResponse
+    public function update(Request $request, Label $label): JsonResponse
     {
-        if (Label::whereId($id)->update(['name' => $request->input('name'), 'sort' => $request->input('sort')])) {
+        if ($label->update(['name' => $request->input('name'), 'sort' => $request->input('sort')])) {
             return Response::json(['status' => 'success', 'message' => '编辑成功']);
         }
 
@@ -38,10 +37,10 @@ class LabelController extends Controller
     }
 
     // 删除标签
-    public function destroy($id): ?JsonResponse
+    public function destroy(Label $label): ?JsonResponse
     {
         try {
-            Label::whereId($id)->delete();
+            $label->delete();
 
             return Response::json(['status' => 'success', 'message' => '删除成功']);
         } catch (Exception $e) {

+ 10 - 19
app/Http/Controllers/Admin/CouponController.php

@@ -43,9 +43,7 @@ class CouponController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['couponList'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.coupon.index', $view);
+        return view('admin.coupon.index', ['couponList' => $query->latest()->paginate(15)->appends($request->except('page'))]);
     }
 
     // 添加优惠券页面
@@ -71,19 +69,12 @@ class CouponController extends Controller
         }
         try {
             $num = (int) $request->input('num');
+            $data = $request->only(['name', 'type', 'usable_times', 'value', 'rule', 'start_time', 'end_time']);
+            $data['logo'] = $logo;
 
             for ($i = 0; $i < $num; $i++) {
-                $obj = new Coupon();
-                $obj->name = $request->input('name');
-                $obj->logo = $logo;
-                $obj->sn = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8);
-                $obj->type = $request->input('type');
-                $obj->usable_times = $request->input('usable_times');
-                $obj->value = $request->input('value');
-                $obj->rule = $request->input('rule');
-                $obj->start_time = strtotime($request->input('start_time'));
-                $obj->end_time = strtotime($request->input('end_time'));
-                $obj->save();
+                $data['sn'] = $num === 1 && $request->input('sn') ? $request->input('sn') : Str::random(8);
+                Coupon::create($data);
             }
 
             return Redirect::route('admin.coupon.index')->with('successMsg', '生成成功');
@@ -95,10 +86,10 @@ class CouponController extends Controller
     }
 
     // 删除优惠券
-    public function destroy($id): JsonResponse
+    public function destroy(Coupon $coupon): JsonResponse
     {
         try {
-            if (Coupon::find($id)->delete()) {
+            if ($coupon->delete()) {
                 return Response::json(['status' => 'success', 'message' => '删除成功']);
             }
         } catch (Exception $e) {
@@ -132,7 +123,7 @@ class CouponController extends Controller
             $sheet->setTitle('抵用券');
             $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '金额(元)', '使用限制(元)'], null);
             foreach ($voucherList as $k => $vo) {
-                $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time);
+                $dateRange = $vo->start_time.' ~ '.$vo->end_time;
                 $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2));
             }
 
@@ -143,7 +134,7 @@ class CouponController extends Controller
             $sheet->setTitle('折扣券');
             $sheet->fromArray(['名称', '使用次数', '有效期', '券码', '折扣(折)', '使用限制(元)'], null);
             foreach ($discountCouponList as $k => $vo) {
-                $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time);
+                $dateRange = $vo->start_time.' ~ '.$vo->end_time;
                 $sheet->fromArray([$vo->name, $vo->usable_times ?? '无限制', $dateRange, $vo->sn, $vo->value, $vo->rule], null, 'A'.($k + 2));
             }
 
@@ -154,7 +145,7 @@ class CouponController extends Controller
             $sheet->setTitle('充值券');
             $sheet->fromArray(['名称', '有效期', '券码', '金额(元)'], null);
             foreach ($refillList as $k => $vo) {
-                $dateRange = date('Y-m-d', $vo->start_time).' ~ '.date('Y-m-d', $vo->end_time);
+                $dateRange = $vo->start_time.' ~ '.$vo->end_time;
                 $sheet->fromArray([$vo->name, $dateRange, $vo->sn, $vo->value], null, 'A'.($k + 2));
             }
 

+ 27 - 57
app/Http/Controllers/Admin/LogsController.php

@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Admin;
 use App\Components\IP;
 use App\Http\Controllers\Controller;
 use App\Models\Node;
-use App\Models\NodeOnlineUserIp;
+use App\Models\NodeOnlineIp;
 use App\Models\NotificationLog;
 use App\Models\Order;
 use App\Models\PaymentCallback;
@@ -15,7 +15,6 @@ use App\Models\UserCreditLog;
 use App\Models\UserDataFlowLog;
 use App\Models\UserDataModifyLog;
 use Illuminate\Http\Request;
-use Redirect;
 
 class LogsController extends Controller
 {
@@ -78,9 +77,7 @@ class LogsController extends Controller
             $query->orderByDesc('id');
         }
 
-        $view['orderList'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.logs.order', $view);
+        return view('admin.logs.order', ['orders' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 流量日志
@@ -123,20 +120,18 @@ class LogsController extends Controller
             $query->where('log_time', '<=', strtotime($endTime));
         }
 
-        // 已使用流量
-        $view['totalTraffic'] = flowAutoShow($query->sum('u') + $query->sum('d'));
-
-        $list = $query->latest('log_time')->paginate(20)->appends($request->except('page'));
-        foreach ($list as $vo) {
-            $vo->u = flowAutoShow($vo->u);
-            $vo->d = flowAutoShow($vo->d);
-            $vo->log_time = date('Y-m-d H:i:s', $vo->log_time);
+        $dataFlowLogs = $query->latest('log_time')->paginate(20)->appends($request->except('page'));
+        foreach ($dataFlowLogs as $log) {
+            $log->u = flowAutoShow($log->u);
+            $log->d = flowAutoShow($log->d);
+            $log->log_time = date('Y-m-d H:i:s', $log->log_time);
         }
 
-        $view['list'] = $list;
-        $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->latest()->get();
-
-        return view('admin.logs.traffic', $view);
+        return view('admin.logs.traffic', [
+            'totalTraffic' => flowAutoShow($query->sum('u') + $query->sum('d')), // 已使用流量
+            'dataFlowLogs' => $dataFlowLogs,
+            'nodes' => Node::whereStatus(1)->orderByDesc('sort')->latest()->get(),
+        ]);
     }
 
     // 邮件发送日志列表
@@ -155,9 +150,7 @@ class LogsController extends Controller
             $query->whereType($type);
         }
 
-        $view['list'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.logs.notification', $view);
+        return view('admin.logs.notification', ['notificationLogs' => $query->latest()->paginate(15)->appends($request->except('page'))]);
     }
 
     // 在线IP监控(实时)
@@ -168,7 +161,7 @@ class LogsController extends Controller
         $port = $request->input('port');
         $nodeId = $request->input('nodeId');
 
-        $query = NodeOnlineUserIp::with(['node:id,name', 'user:id,email'])->where('created_at', '>=', strtotime('-2 minutes'));
+        $query = NodeOnlineIp::with(['node:id,name', 'user:id,email'])->where('created_at', '>=', strtotime('-2 minutes'));
 
         if (isset($ip)) {
             $query->whereIp($ip);
@@ -209,10 +202,10 @@ class LogsController extends Controller
             $log->ipInfo = implode(' ', $ipInfo);
         }
 
-        $view['list'] = $onlineIPLogs;
-        $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->latest()->get();
-
-        return view('admin.logs.onlineIPMonitor', $view);
+        return view('admin.logs.onlineIPMonitor', [
+            'onlineIPLogs' => $onlineIPLogs,
+            'nodes' => Node::whereStatus(1)->orderByDesc('sort')->latest()->get(),
+        ]);
     }
 
     // 用户余额变动记录
@@ -228,9 +221,7 @@ class LogsController extends Controller
             });
         }
 
-        $view['list'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.logs.userCreditHistory', $view);
+        return view('admin.logs.userCreditHistory', ['userCreditLogs' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 用户封禁记录
@@ -246,9 +237,7 @@ class LogsController extends Controller
             });
         }
 
-        $view['list'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.logs.userBanHistory', $view);
+        return view('admin.logs.userBanHistory', ['userBanLogs' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 用户流量变动记录
@@ -264,9 +253,7 @@ class LogsController extends Controller
             });
         }
 
-        $view['list'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.logs.userTraffic', $view);
+        return view('admin.logs.userTraffic', ['userTrafficLogs' => $query->latest()->paginate(15)->appends($request->except('page'))]);
     }
 
     // 用户在线IP记录
@@ -297,34 +284,19 @@ class LogsController extends Controller
 
         $userList = $query->paginate(15)->appends($request->except('page'));
 
-        $nodeOnlineIPs = NodeOnlineUserIp::with('node:id,name')->where('created_at', '>=', strtotime('-10 minutes'))->latest()->distinct();
-        // Todo 优化查询
+        $nodeOnlineIPs = NodeOnlineIp::with('node:id,name')->where('created_at', '>=', strtotime('-10 minutes'))->latest()->distinct()->get();
         foreach ($userList as $user) {
             // 最近5条在线IP记录,如果后端设置为60秒上报一次,则为10分钟内的在线IP
-            $user->onlineIPList = $nodeOnlineIPs->wherePort($user->port)->limit(5)->get();
+            $user->onlineIPList = $nodeOnlineIPs->where('port', '==', $user->port)->chunk(5);
         }
 
-        $view['userList'] = $userList;
-
-        return view('admin.logs.userOnlineIP', $view);
+        return view('admin.logs.userOnlineIP', ['userList' => $userList]);
     }
 
     // 用户流量监控
-    public function userTrafficMonitor($id)
+    public function userTrafficMonitor(User $user)
     {
-        if (empty($id)) {
-            return Redirect::back();
-        }
-
-        $user = User::find($id);
-        if (empty($user)) {
-            return Redirect::back();
-        }
-
-        $view['email'] = $user->email;
-        $view = array_merge($view, $this->dataFlowChart($user->id));
-
-        return view('admin.logs.userMonitor', $view);
+        return view('admin.logs.userMonitor', array_merge(['email' => $user->email], $this->dataFlowChart($user->id)));
     }
 
     // 回调日志
@@ -338,8 +310,6 @@ class LogsController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['list'] = $query->latest()->paginate(10)->appends($request->except('page'));
-
-        return view('admin.logs.callback', $view);
+        return view('admin.logs.callback', ['callbackLogs' => $query->latest()->paginate(10)->appends($request->except('page'))]);
     }
 }

+ 2 - 6
app/Http/Controllers/Admin/MarketingController.php

@@ -31,9 +31,7 @@ class MarketingController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['list'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.marketing.emailList', $view);
+        return view('admin.marketing.emailList', ['emails' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 消息通道群发列表
@@ -47,9 +45,7 @@ class MarketingController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['list'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.marketing.pushList', $view);
+        return view('admin.marketing.pushList', ['pushes' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 添加推送消息

+ 62 - 0
app/Http/Controllers/Admin/NodeAuthController.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Controllers\Controller;
+use App\Models\NodeAuth;
+use Exception;
+use Illuminate\Http\Request;
+
+class NodeAuthController extends Controller
+{
+    // 节点授权列表
+    public function index()
+    {
+        return view('admin.node.auth', ['authorizations' => NodeAuth::orderBy('node_id')->paginate()->appends(request('page'))]);
+    }
+
+    // 添加节点授权
+    public function store(Request $request)
+    {
+        $nodeArray = Node::whereStatus(1)->orderBy('id')->pluck('id')->toArray();
+        $authArray = NodeAuth::orderBy('node_id')->pluck('node_id')->toArray();
+
+        $arrayDifferent = array_diff($nodeArray, $authArray);
+
+        if (empty($arrayDifferent)) {
+            return Response::json(['status' => 'success', 'message' => '没有需要生成授权的节点']);
+        }
+
+        foreach ($arrayDifferent as $nodeId) {
+            $obj = new NodeAuth();
+            $obj->node_id = $nodeId;
+            $obj->key = Str::random();
+            $obj->secret = Str::random(8);
+            $obj->save();
+        }
+
+        return Response::json(['status' => 'success', 'message' => '生成成功']);
+    }
+
+    // 重置节点授权
+    public function update(NodeAuth $auth)
+    {
+        if ($auth->update(['key' => Str::random(), 'secret' => Str::random(8)])) {
+            return Response::json(['status' => 'success', 'message' => '操作成功']);
+        }
+
+        return Response::json(['status' => 'fail', 'message' => '操作失败']);
+    }
+
+    // 删除节点授权
+    public function destroy(NodeAuth $auth)
+    {
+        try {
+            $auth->delete();
+        } catch (Exception $e) {
+            return Response::json(['status' => 'fail', 'message' => '错误:'.var_export($e, true)]);
+        }
+
+        return Response::json(['status' => 'success', 'message' => '操作成功']);
+    }
+}

+ 31 - 108
app/Http/Controllers/Admin/NodeController.php

@@ -10,18 +10,15 @@ use App\Models\Country;
 use App\Models\Label;
 use App\Models\Level;
 use App\Models\Node;
-use App\Models\NodeAuth;
 use App\Models\NodeCertificate;
 use App\Models\NodePing;
+use App\Models\RuleGroup;
 use App\Services\NodeService;
 use Exception;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Log;
-use Redirect;
 use Response;
-use Session;
-use Str;
 
 class NodeController extends Controller
 {
@@ -52,19 +49,18 @@ class NodeController extends Controller
             $node->uptime = empty($node_info) ? 0 : seconds2time($node_info->uptime);
         }
 
-        $view['nodeList'] = $nodeList;
-
-        return view('admin.node.index', $view);
+        return view('admin.node.index', ['nodeList' => $nodeList]);
     }
 
     // 添加节点页面
     public function create()
     {
         return view('admin.node.info', [
-            'countryList' => Country::orderBy('code')->get(),
-            'levelList' => Level::orderBy('level')->get(),
-            'labelList' => Label::orderByDesc('sort')->orderBy('id')->get(),
-            'dvList' => NodeCertificate::orderBy('id')->get(),
+            'countries' => Country::orderBy('code')->get(),
+            'levels' => Level::orderBy('level')->get(),
+            'ruleGroups' => RuleGroup::orderBy('id')->get(),
+            'labels' => Label::orderByDesc('sort')->orderBy('id')->get(),
+            'certs' => NodeCertificate::orderBy('id')->get(),
         ]);
     }
 
@@ -76,8 +72,8 @@ class NodeController extends Controller
 
             if ($node) {
                 // 生成节点标签
-                if ($request->exists('labels')) {
-                    (new NodeService())->makeLabels($node->id, $request->input('labels'));
+                if ($request->has('labels')) {
+                    $node->labels()->attach($request->input('labels'));
                 }
 
                 return Response::json(['status' => 'success', 'message' => '添加成功']);
@@ -92,27 +88,24 @@ class NodeController extends Controller
     }
 
     // 编辑节点页面
-    public function edit($id)
+    public function edit(Node $node)
     {
         return view('admin.node.info', [
-            'node' => Node::with('labels')->find($id),
-            'countryList' => Country::orderBy('code')->get(),
-            'levelList' => Level::orderBy('level')->get(),
-            'labelList' => Label::orderByDesc('sort')->orderBy('id')->get(),
-            'dvList' => NodeCertificate::orderBy('id')->get(),
+            'node' => $node,
+            'countries' => Country::orderBy('code')->get(),
+            'levels' => Level::orderBy('level')->get(),
+            'ruleGroups' => RuleGroup::orderBy('id')->get(),
+            'labels' => Label::orderByDesc('sort')->orderBy('id')->get(),
+            'certs' => NodeCertificate::orderBy('id')->get(),
         ]);
     }
 
     // 编辑节点
-    public function update(NodeRequest $request, $id): JsonResponse
+    public function update(NodeRequest $request, Node $node): JsonResponse
     {
-        $node = Node::find($id);
-
         try {
-            // 生成节点标签
-            if ($request->exists('labels')) {
-                (new NodeService())->makeLabels($node->id, $request->input('labels'));
-            }
+            // 更新节点标签
+            $node->labels()->sync($request->input('labels'));
 
             if ($node->update($request->except('_token', 'labels'))) {
                 return Response::json(['status' => 'success', 'message' => '编辑成功']);
@@ -127,10 +120,8 @@ class NodeController extends Controller
     }
 
     // 删除节点
-    public function destroy($id): JsonResponse
+    public function destroy(Node $node): JsonResponse
     {
-        $node = Node::findOrFail($id);
-
         try {
             if ($node->delete()) {
                 return Response::json(['status' => 'success', 'message' => '删除成功']);
@@ -145,9 +136,8 @@ class NodeController extends Controller
     }
 
     // 节点信息验证
-    public function checkNode($id): JsonResponse
+    public function checkNode(Node $node): JsonResponse
     {
-        $node = Node::find($id);
         // 使用DDNS的node先获取ipv4地址
         if ($node->is_ddns) {
             $ip = gethostbyname($node->server);
@@ -174,9 +164,9 @@ class NodeController extends Controller
     }
 
     // 重载节点
-    public function reload($id): JsonResponse
+    public function reload(Node $node): JsonResponse
     {
-        if (reloadNode::dispatchNow(Node::whereId($id)->get())) {
+        if (reloadNode::dispatchNow($node)) {
             return Response::json(['status' => 'success', 'message' => '重载成功!']);
         }
 
@@ -184,27 +174,14 @@ class NodeController extends Controller
     }
 
     // 节点流量监控
-    public function nodeMonitor($id)
+    public function nodeMonitor(Node $node)
     {
-        $node = Node::find($id);
-        if (! $node) {
-            Session::flash('errorMsg', '节点不存在,请重试');
-
-            return Redirect::back();
-        }
-
-        $view['nodeName'] = $node->name;
-        $view['nodeServer'] = $node->server;
-        $view = array_merge($view, $this->DataFlowChart($node->id, true));
-
-        return view('admin.node.monitor', $view);
+        return view('admin.node.monitor', array_merge(['nodeName' => $node->name, 'nodeServer' => $node->server], $this->DataFlowChart($node->id, true)));
     }
 
     // Ping节点延迟
-    public function pingNode($id): JsonResponse
+    public function pingNode(Node $node): JsonResponse
     {
-        $node = Node::findOrFail($id);
-
         $result = NetworkDetection::ping($node->is_ddns ? $node->server : $node->ip);
 
         if ($result) {
@@ -225,69 +202,15 @@ class NodeController extends Controller
     // Ping节点延迟日志
     public function pingLog(Request $request)
     {
-        $node_id = $request->input('nodeId');
+        $node_id = $request->input('id');
         $query = NodePing::query();
         if (isset($node_id)) {
             $query->whereNodeId($node_id);
         }
 
-        $view['nodeList'] = Node::orderBy('id')->get();
-        $view['pingLogs'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.node.ping', $view);
-    }
-
-    // 节点授权列表
-    public function authList(Request $request)
-    {
-        $view['list'] = NodeAuth::orderBy('node_id')->paginate(15)->appends($request->except('page'));
-
-        return view('admin.node.auth', $view);
-    }
-
-    // 添加节点授权
-    public function addAuth(): JsonResponse
-    {
-        $nodeArray = Node::whereStatus(1)->orderBy('id')->pluck('id')->toArray();
-        $authArray = NodeAuth::orderBy('node_id')->pluck('node_id')->toArray();
-
-        $arrayDifferent = array_diff($nodeArray, $authArray);
-
-        if (empty($arrayDifferent)) {
-            return Response::json(['status' => 'success', 'message' => '没有需要生成授权的节点']);
-        }
-
-        foreach ($arrayDifferent as $nodeId) {
-            $obj = new NodeAuth();
-            $obj->node_id = $nodeId;
-            $obj->key = Str::random();
-            $obj->secret = Str::random(8);
-            $obj->save();
-        }
-
-        return Response::json(['status' => 'success', 'message' => '生成成功']);
-    }
-
-    // 删除节点授权
-    public function delAuth($id): JsonResponse
-    {
-        try {
-            NodeAuth::whereId($id)->delete();
-        } catch (Exception $e) {
-            return Response::json(['status' => 'fail', 'message' => '错误:'.var_export($e, true)]);
-        }
-
-        return Response::json(['status' => 'success', 'message' => '操作成功']);
-    }
-
-    // 重置节点授权
-    public function refreshAuth($id): JsonResponse
-    {
-        $ret = NodeAuth::find($id)->update(['key' => Str::random(), 'secret' => Str::random(8)]);
-        if ($ret) {
-            return Response::json(['status' => 'success', 'message' => '操作成功']);
-        }
-
-        return Response::json(['status' => 'fail', 'message' => '操作失败']);
+        return view('admin.node.ping', [
+            'nodeList' => Node::orderBy('id')->get(),
+            'pingLogs' => $query->latest()->paginate(15)->appends($request->except('page')),
+        ]);
     }
 }

+ 9 - 25
app/Http/Controllers/Admin/PermissionController.php

@@ -3,17 +3,15 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
-use Illuminate\Http\Request;
-use Illuminate\Http\Response;
+use App\Http\Requests\Admin\PermissionRequest;
+use Exception;
 use Spatie\Permission\Models\Permission;
 
 class PermissionController extends Controller
 {
     public function index()
     {
-        $permissions = Permission::query()->paginate(15);
-
-        return view('admin.permission.index', compact('permissions'));
+        return view('admin.permission.index', ['permissions' => Permission::query()->paginate(15)]);
     }
 
     public function create()
@@ -21,17 +19,9 @@ class PermissionController extends Controller
         return view('admin.permission.info');
     }
 
-    public function store(Request $request)
+    public function store(PermissionRequest $request)
     {
-        $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']);
-
-        if ($validator->fails()) {
-            return redirect()->back()->withInput()->withErrors($validator->errors());
-        }
-
-        $permission = Permission::create($request->all());
-
-        if ($permission) {
+        if ($permission = Permission::create($request->validated())) {
             return redirect()->route('admin.permission.edit', $permission)->with('successMsg', '操作成功');
         }
 
@@ -43,15 +33,9 @@ class PermissionController extends Controller
         return view('admin.permission.info', compact('permission'));
     }
 
-    public function update(Request $request, Permission $permission)
+    public function update(PermissionRequest $request, Permission $permission)
     {
-        $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']);
-
-        if ($validator->fails()) {
-            return redirect()->back()->withInput()->withErrors($validator->errors());
-        }
-
-        if ($permission->update($request->all())) {
+        if ($permission->update($request->validated())) {
             return redirect()->back()->with('successMsg', '操作成功');
         }
 
@@ -63,9 +47,9 @@ class PermissionController extends Controller
         try {
             $permission->delete();
         } catch (Exception $e) {
-            return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
+            return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
         }
 
-        return Response::json(['status' => 'success', 'message' => '清理成功']);
+        return response()->json(['status' => 'success', 'message' => '清理成功']);
     }
 }

+ 18 - 34
app/Http/Controllers/Admin/RoleController.php

@@ -3,8 +3,8 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
-use Illuminate\Http\Request;
-use Illuminate\Http\Response;
+use App\Http\Requests\Admin\RoleRequest;
+use Exception;
 use Spatie\Permission\Models\Permission;
 use Spatie\Permission\Models\Role;
 
@@ -12,29 +12,19 @@ class RoleController extends Controller
 {
     public function index()
     {
-        $roles = Role::with('permissions')->paginate(15);
-
-        return view('admin.role.index', compact('roles'));
+        return view('admin.role.index', ['roles' => Role::with('permissions')->paginate(15)]);
     }
 
     public function create()
     {
-        $permissions = Permission::all()->pluck('description', 'name');
-
-        return view('admin.role.info', compact('permissions'));
+        return view('admin.role.info', ['permissions' => Permission::all()->pluck('description', 'name')]);
     }
 
-    public function store(Request $request)
+    public function store(RoleRequest $request)
     {
-        $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']);
+        if ($role = Role::create($request->only(['name', 'description']))) {
+            $role->givePermissionTo($request->input('permissions') ?: []);
 
-        if ($validator->fails()) {
-            return redirect()->back()->withInput()->withErrors($validator->errors());
-        }
-
-        $role = Role::create($request->except('permissions'));
-        $permissions = $request->input('permissions') ?: [];
-        if ($role->givePermissionTo($permissions)) {
             return redirect()->route('admin.role.edit', $role)->with('successMsg', '操作成功');
         }
 
@@ -43,27 +33,21 @@ class RoleController extends Controller
 
     public function edit(Role $role)
     {
-        $role->load('permissions');
-        $permissions = Permission::all()->pluck('description', 'name');
-
-        return view('admin.role.info', compact('role', 'permissions'));
+        return view('admin.role.info', [
+            'role' => $role->load('permissions'),
+            'permissions' => Permission::all()->pluck('description', 'name'),
+        ]);
     }
 
-    public function update(Request $request, Role $role)
+    public function update(RoleRequest $request, Role $role)
     {
-        $validator = validator()->make($request->all(), ['name' => 'required', 'description' => 'required']);
-
-        if ($validator->fails()) {
-            return redirect()->back()->withInput()->withErrors($validator->errors());
-        }
-
         if ($role->name === 'Super Admin') {
             return redirect()->back()->withInput()->withErrors('请勿修改超级管理员');
         }
 
-        $role->update($request->except('permissions'));
-        $permissions = $request->input('permissions') ?: [];
-        if ($role->syncPermissions($permissions)) {
+        if ($role->update($request->only(['name', 'description']))) {
+            $role->syncPermissions($request->input('permissions') ?: []);
+
             return redirect()->back()->with('successMsg', '操作成功');
         }
 
@@ -74,13 +58,13 @@ class RoleController extends Controller
     {
         try {
             if ($role->name === 'Super Admin') {
-                return Response::json(['status' => 'fail', 'message' => '请勿删除超级管理员']);
+                return response()->json(['status' => 'fail', 'message' => '请勿删除超级管理员']);
             }
             $role->delete();
         } catch (Exception $e) {
-            return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
+            return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
         }
 
-        return Response::json(['status' => 'success', 'message' => '清理成功']);
+        return response()->json(['status' => 'success', 'message' => '清理成功']);
     }
 }

+ 15 - 42
app/Http/Controllers/Admin/RuleController.php

@@ -3,15 +3,14 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
+use App\Http\Requests\Admin\RuleRequest;
 use App\Models\Node;
 use App\Models\Rule;
-use App\Models\RuleGroup;
 use App\Models\RuleLog;
 use Exception;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Response;
-use Validator;
 
 class RuleController extends Controller
 {
@@ -25,31 +24,13 @@ class RuleController extends Controller
             $query->whereType($type);
         }
 
-        $view['rules'] = $query->paginate(15)->appends($request->except('page'));
-
-        return view('admin.rule.index', $view);
+        return view('admin.rule.index', ['rules' => $query->paginate(15)->appends($request->except('page'))]);
     }
 
     // 添加审计规则
-    public function store(Request $request): JsonResponse
+    public function store(RuleRequest $request): JsonResponse
     {
-        $validator = Validator::make($request->all(), [
-            'type' => 'required|between:1,4',
-            'name' => 'required',
-            'pattern' => 'required',
-        ]);
-
-        if ($validator->fails()) {
-            return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]);
-        }
-
-        $rule = new Rule();
-        $rule->type = $request->input('type');
-        $rule->name = $request->input('name');
-        $rule->pattern = $request->input('pattern');
-        $rule->save();
-
-        if ($rule->id) {
+        if (Rule::create($request->validated())) {
             return Response::json(['status' => 'success', 'message' => '提交成功']);
         }
 
@@ -57,9 +38,9 @@ class RuleController extends Controller
     }
 
     // 编辑审计规则
-    public function update(Request $request, $id): JsonResponse
+    public function update(RuleRequest $request, Rule $rule): JsonResponse
     {
-        if (Rule::find($id)->update(['name' => $request->input('rule_name'), 'pattern' => $request->input('rule_pattern')])) {
+        if ($rule->update($request->validated())) {
             return Response::json(['status' => 'success', 'message' => '操作成功']);
         }
 
@@ -67,18 +48,10 @@ class RuleController extends Controller
     }
 
     // 删除审计规则
-    public function destroy($id): JsonResponse
+    public function destroy(Rule $rule): JsonResponse
     {
         try {
-            Rule::whereId($id)->delete();
-
-            foreach (RuleGroup::all() as $ruleGroup) {
-                $rules = $ruleGroup->rules;
-                if ($rules && in_array($id, $rules, true)) {
-                    $ruleGroup->rules = array_merge(array_diff($rules, [$id]));
-                    $ruleGroup->save();
-                }
-            }
+            $rule->delete();
         } catch (Exception $e) {
             return Response::json(['status' => 'fail', 'message' => '操作失败, '.$e->getMessage()]);
         }
@@ -110,11 +83,11 @@ class RuleController extends Controller
             $query->whereRuleId($ruleId);
         }
 
-        $view['nodeList'] = Node::all();
-        $view['ruleList'] = Rule::all();
-        $view['ruleLogs'] = $query->latest()->paginate(15)->appends($request->except('page'));
-
-        return view('admin.rule.log', $view);
+        return view('admin.rule.log', [
+            'nodes' => Node::all(),
+            'rules' => Rule::all(),
+            'ruleLogs' => $query->latest()->paginate(15)->appends($request->except('page')),
+        ]);
     }
 
     // 清除所有审计触发日志
@@ -125,8 +98,8 @@ class RuleController extends Controller
         } catch (Exception $e) {
             return Response::json(['status' => 'fail', 'message' => '清理失败, '.$e->getMessage()]);
         }
-        $result = RuleLog::doesntExist();
-        if ($ret || $result) {
+
+        if ($ret || RuleLog::doesntExist()) {
             return Response::json(['status' => 'success', 'message' => '清理成功']);
         }
 

+ 23 - 102
app/Http/Controllers/Admin/RuleGroupController.php

@@ -3,146 +3,67 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
-use App\Models\Node;
+use App\Http\Requests\Admin\RuleGroupRequest;
 use App\Models\Rule;
 use App\Models\RuleGroup;
-use App\Models\RuleGroupNode;
 use Exception;
-use Illuminate\Http\JsonResponse;
-use Illuminate\Http\RedirectResponse;
-use Illuminate\Http\Request;
-use Redirect;
-use Response;
-use Validator;
 
 class RuleGroupController extends Controller
 {
     // 审计规则分组列表
-    public function index(Request $request)
+    public function index()
     {
-        $view['ruleGroupList'] = RuleGroup::paginate(15)->appends($request->except('page'));
-
-        return view('admin.rule.group.index', $view);
+        return view('admin.rule.group.index', ['ruleGroups' => RuleGroup::paginate(15)->appends(request('page'))]);
     }
 
     // 添加审计规则分组页面
     public function create()
     {
-        $view['ruleList'] = Rule::all();
-
-        return view('admin.rule.group.info', $view);
+        return view('admin.rule.group.info', ['rules' => Rule::all()]);
     }
 
     // 添加审计规则分组
-    public function store(Request $request): RedirectResponse
+    public function store(RuleGroupRequest $request)
     {
-        $validator = Validator::make($request->all(), [
-            'name' => 'required',
-            'type' => 'required|boolean',
-            'rules' => 'required',
-        ]);
+        if ($group = RuleGroup::create($request->only('name', 'type'))) {
+            $group->rules()->attach($request->input('rules'));
 
-        if ($validator->fails()) {
-            return Redirect::back()->withInput()->withErrors($validator->errors());
+            return redirect(route('admin.rule.group.edit', $group))->with('successMsg', '操作成功');
         }
 
-        $obj = new RuleGroup();
-        $obj->name = $request->input('name');
-        $obj->type = (int) $request->input('type');
-        $obj->rules = $request->input('rules');
-        $obj->save();
-
-        if ($obj->id) {
-            return Redirect::back()->with('successMsg', '操作成功');
-        }
-
-        return Redirect::back()->withInput()->withErrors('操作失败');
+        return redirect()->back()->withInput()->withErrors('操作失败');
     }
 
     // 编辑审计规则分组页面
-    public function edit($id)
+    public function edit(RuleGroup $group)
     {
-        $view['ruleGroup'] = RuleGroup::find($id);
-        $view['ruleList'] = Rule::all();
-
-        return view('admin.rule.group.info', $view);
+        return view('admin.rule.group.info', [
+            'ruleGroup' => $group,
+            'rules' => Rule::all(),
+        ]);
     }
 
     // 编辑审计规则分组
-    public function update(Request $request, $id): RedirectResponse
+    public function update(RuleGroupRequest $request, RuleGroup $group)
     {
-        $validator = Validator::make($request->all(), [
-            'name' => 'required',
-            'type' => 'required|boolean',
-        ]);
-        if ($validator->fails()) {
-            return Redirect::back()->withInput()->withErrors($validator->errors());
-        }
+        if ($group->update($request->only(['name', 'type']))) {
+            $group->rules()->sync($request->input('rules'));
 
-        $ret = RuleGroup::find($id)->update([
-            'name' => $request->input('name'),
-            'type' => $request->input('type'),
-            'rules' => $request->input('rules'),
-        ]);
-
-        if ($ret) {
-            return Redirect::back()->with('successMsg', '操作成功');
+            return redirect()->back()->with('successMsg', '操作成功');
         }
 
-        return Redirect::back()->withInput()->withErrors('操作失败');
+        return redirect()->back()->withInput()->withErrors('操作失败');
     }
 
     // 删除审计规则分组
-    public function destroy($id): JsonResponse
+    public function destroy(RuleGroup $group)
     {
         try {
-            RuleGroup::whereId($id)->delete();
-        } catch (Exception $e) {
-            return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
-        }
-
-        return Response::json(['status' => 'success', 'message' => '清理成功']);
-    }
-
-    // 规则分组关联节点
-    public function assignNode($id)
-    {
-        $view['ruleGroup'] = RuleGroup::find($id);
-        $view['nodeList'] = Node::all();
-
-        return view('admin.rule.group.assign', $view);
-    }
-
-    // 规则分组关联节点
-    public function assign(Request $request, $id)
-    {
-        $nodes = $request->input('nodes');
-        $ruleGroup = RuleGroup::findOrFail($id);
-
-        try {
-            if ($ruleGroup->nodes === $nodes) {
-                return Redirect::back()->with('successMsg', '检测为未修改,无变动!');
-            }
-            RuleGroupNode::whereRuleGroupId($id)->delete();
-            if ($nodes) {
-                $ruleGroup->nodes = $nodes;
-                if (! $ruleGroup->save()) {
-                    return Redirect::back()->withErrors('更新错误!');
-                }
-
-                foreach ($nodes as $nodeId) {
-                    $obj = new RuleGroupNode();
-                    $obj->rule_group_id = $id;
-                    $obj->node_id = $nodeId;
-                    $obj->save();
-                }
-            } else {
-                RuleGroup::find($id)->update(['nodes' => null]);
-            }
+            $group->delete();
         } catch (Exception $e) {
-            return Redirect::back()->withInput()->withErrors($e->getMessage());
+            return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
         }
 
-        return Redirect::back()->with('successMsg', '操作成功');
+        return response()->json(['status' => 'success', 'message' => '清理成功']);
     }
 }

+ 13 - 24
app/Http/Controllers/Admin/ShopController.php

@@ -17,11 +17,6 @@ use Redirect;
 use Response;
 use Str;
 
-/**
- * 商店控制器.
- *
- * Class ShopController
- */
 class ShopController extends Controller
 {
     // 商品列表
@@ -40,17 +35,13 @@ class ShopController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['goodsList'] = $query->orderByDesc('status')->paginate(10)->appends($request->except('page'));
-
-        return view('admin.shop.index', $view);
+        return view('admin.shop.index', ['goodsList' => $query->orderByDesc('status')->paginate(10)->appends($request->except('page'))]);
     }
 
     // 添加商品页面
     public function create()
     {
-        $view['levelList'] = Level::orderBy('level')->get();
-
-        return view('admin.shop.info', $view);
+        return view('admin.shop.info', ['levels' => Level::orderBy('level')->get()]);
     }
 
     // 添加商品
@@ -71,10 +62,9 @@ class ShopController extends Controller
                     return $path;
                 }
             }
-            $good = Goods::create($data);
 
-            if ($good) {
-                return Redirect::route('admin.goods.edit', $good->id)->with('successMsg', '添加成功');
+            if ($good = Goods::create($data)) {
+                return Redirect::route('admin.goods.edit', $good)->with('successMsg', '添加成功');
             }
         } catch (Exception $e) {
             Log::error('添加商品信息异常:'.$e->getMessage());
@@ -99,18 +89,17 @@ class ShopController extends Controller
     }
 
     // 编辑商品页面
-    public function edit($id)
+    public function edit(Goods $good)
     {
-        $view['goods'] = Goods::find($id);
-        $view['levelList'] = Level::orderBy('level')->get();
-
-        return view('admin.shop.info', $view);
+        return view('admin.shop.info', [
+            'good' => $good,
+            'levels' => Level::orderBy('level')->get(),
+        ]);
     }
 
     // 编辑商品
-    public function update(ShopUpdateRequest $request, $id)
+    public function update(ShopUpdateRequest $request, Goods $good)
     {
-        $goods = Goods::findOrFail($id);
         $data = $request->except('_token', '_method', 'logo');
         // 商品LOGO
         if ($request->hasFile('logo')) {
@@ -126,7 +115,7 @@ class ShopController extends Controller
             $data['is_hot'] = $request->input('is_hot') ? 1 : 0;
             $data['status'] = $request->input('status') ? 1 : 0;
 
-            if ($goods->update($data)) {
+            if ($good->update($data)) {
                 return Redirect::back()->with('successMsg', '编辑成功');
             }
         } catch (Exception $e) {
@@ -139,10 +128,10 @@ class ShopController extends Controller
     }
 
     // 删除商品
-    public function destroy($id): JsonResponse
+    public function destroy(Goods $good): JsonResponse
     {
         try {
-            if (Goods::find($id)->delete()) {
+            if ($good->delete()) {
                 return Response::json(['status' => 'success', 'message' => '删除成功']);
             }
         } catch (Exception $e) {

+ 4 - 14
app/Http/Controllers/Admin/SubscribeController.php

@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Admin;
 use App\Http\Controllers\Controller;
 use App\Models\UserSubscribe;
 use App\Models\UserSubscribeLog;
-use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Response;
 
@@ -39,13 +38,11 @@ class SubscribeController extends Controller
             $query->whereStatus($status);
         }
 
-        $view['subscribeList'] = $query->latest()->paginate(20)->appends($request->except('page'));
-
-        return view('admin.subscribe.index', $view);
+        return view('admin.subscribe.index', ['subscribeList' => $query->latest()->paginate(20)->appends($request->except('page'))]);
     }
 
     //订阅记录
-    public function subscribeLog(Request $request, $id)
+    public function subscribeLog($id)
     {
         $query = UserSubscribeLog::with('user:email');
 
@@ -53,19 +50,12 @@ class SubscribeController extends Controller
             $query->whereUserSubscribeId($id);
         }
 
-        $view['subscribeLog'] = $query->latest()->paginate(20)->appends($request->except('page'));
-
-        return view('admin.subscribe.log', $view);
+        return view('admin.subscribe.log', ['subscribeLog' => $query->latest()->paginate(20)->appends(\request('page'))]);
     }
 
     // 设置用户的订阅的状态
-    public function setSubscribeStatus(Request $request, $id): JsonResponse
+    public function setSubscribeStatus(UserSubscribe $subscribe)
     {
-        if (empty($id)) {
-            return Response::json(['status' => 'fail', 'message' => '操作异常']);
-        }
-        $subscribe = UserSubscribe::find($id);
-
         if ($subscribe->status) {
             $subscribe->update(['status' => 0, 'ban_time' => time(), 'ban_desc' => '后台手动封禁']);
         } else {

+ 1 - 4
app/Http/Controllers/Admin/SystemController.php

@@ -16,10 +16,7 @@ class SystemController extends Controller
     // 系统设置
     public function index()
     {
-        $view = Config::pluck('value', 'name')->toArray();
-        $view['labelList'] = Label::orderByDesc('sort')->orderBy('id')->get();
-
-        return view('admin.config.system', $view);
+        return view('admin.config.system', array_merge(['labelList' => Label::orderByDesc('sort')->orderBy('id')->get()], Config::pluck('value', 'name')->toArray()));
     }
 
     // 设置系统扩展信息,例如客服、统计代码

+ 11 - 23
app/Http/Controllers/Admin/TicketController.php

@@ -3,12 +3,10 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Components\Helpers;
-use App\Components\PushNotification;
 use App\Http\Controllers\Controller;
 use App\Mail\closeTicket;
 use App\Mail\replyTicket;
 use App\Models\Ticket;
-use App\Models\TicketReply;
 use App\Models\User;
 use Auth;
 use Illuminate\Http\Request;
@@ -27,7 +25,7 @@ class TicketController extends Controller
     {
         $email = $request->input('email');
 
-        $query = Ticket::whereAdminId(Auth::id())->orwhere('admin_id', null);
+        $query = Ticket::whereAdminId(Auth::id())->orwhere('admin_id');
 
         if (isset($email)) {
             $query->whereHas('user', static function ($q) use ($email) {
@@ -35,9 +33,7 @@ class TicketController extends Controller
             });
         }
 
-        $view['ticketList'] = $query->latest()->paginate(10)->appends($request->except('page'));
-
-        return view('admin.ticket.index', $view);
+        return view('admin.ticket.index', ['ticketList' => $query->latest()->paginate(10)->appends($request->except('page'))]);
     }
 
     // 创建工单
@@ -76,28 +72,22 @@ class TicketController extends Controller
     }
 
     // 回复
-    public function edit($id)
+    public function edit(Ticket $ticket)
     {
-        $view['ticket'] = Ticket::find($id);
-        $view['replyList'] = TicketReply::whereTicketId($id)->oldest()->get();
-
-        return view('admin.ticket.reply', $view);
+        return view('admin.ticket.reply', [
+            'ticket' => $ticket,
+            'replyList' => $ticket->reply()->oldest()->get(),
+        ]);
     }
 
     // 回复工单
-    public function update(Request $request, $id)
+    public function update(Request $request, Ticket $ticket)
     {
         $content = substr(str_replace(['atob', 'eval'], '', clean($request->input('content'))), 0, 300);
 
-        $obj = new TicketReply();
-        $obj->ticket_id = $id;
-        $obj->admin_id = Auth::id();
-        $obj->content = $content;
-
-        if ($obj->save()) {
+        if ($ticket->reply()->create(['admin_id' => Auth::id(), 'content' => $content])) {
             // 将工单置为已回复
-            $ticket = Ticket::with('user')->find($id);
-            Ticket::whereId($id)->update(['status' => 1]);
+            $ticket->update(['status' => 1]);
 
             $title = '工单回复提醒';
             $content = '标题:'.$ticket->title.'<br>管理员回复:'.$content;
@@ -113,10 +103,8 @@ class TicketController extends Controller
     }
 
     // 关闭工单
-    public function destroy($id)
+    public function destroy(Ticket $ticket)
     {
-        $ticket = Ticket::with('user')->find($id);
-
         if (! $ticket->close()) {
             return Response::json(['status' => 'fail', 'message' => '关闭失败']);
         }

+ 2 - 7
app/Http/Controllers/Admin/ToolsController.php

@@ -197,10 +197,7 @@ class ToolsController extends Controller
         }
 
         $logs = $this->tail($file, 10000);
-        if (false === $logs) {
-            $view['urlList'] = [];
-        } else {
-            $url = [];
+        if (false !== $logs) {
             foreach ($logs as $log) {
                 if (str_contains($log, 'TCP connecting')) {
                     continue;
@@ -220,10 +217,8 @@ class ToolsController extends Controller
                     }
                 }
             }
-
-            $view['urlList'] = array_unique($url);
         }
 
-        return view('admin.tools.analysis', $view);
+        return view('admin.tools.analysis', ['urlList' => array_unique($url ?? [])]);
     }
 }

+ 31 - 48
app/Http/Controllers/Admin/UserController.php

@@ -9,16 +9,15 @@ use App\Http\Requests\Admin\UserStoreRequest;
 use App\Http\Requests\Admin\UserUpdateRequest;
 use App\Models\Level;
 use App\Models\Node;
+use App\Models\Order;
 use App\Models\User;
 use App\Models\UserGroup;
 use App\Models\UserHourlyDataFlow;
 use Auth;
-use DB;
 use Exception;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Log;
-use Redirect;
 use Response;
 use Session;
 use Spatie\Permission\Models\Role;
@@ -96,10 +95,16 @@ class UserController extends Controller
         }
 
         // 不活跃用户
-        if ($request->input('unActive')) {
+        if ($request->has('unActive')) {
             $query->whereBetween('t', [1, strtotime('-'.sysConfig('expire_days').' days')])->whereEnable(1);
         }
 
+        // 不活跃用户
+        if ($request->has('paying')) {
+            $payingUser = Order::whereStatus(2)->where('goods_id', '<>', 0)->whereIsExpire(0)->where('amount', '>', 0)->pluck('user_id')->unique();
+            $query->whereIn('id', $payingUser);
+        }
+
         // 1小时内流量异常用户
         if ($flowAbnormal) {
             $query->whereIn('id', (new UserHourlyDataFlow)->trafficAbnormal());
@@ -119,14 +124,12 @@ class UserController extends Controller
             $roles = Role::all()->pluck('description', 'name');
         } elseif (Auth::getUser()->hasPermissionTo('give roles')) {
             $roles = Auth::getUser()->roles();
-        } else {
-            $roles = [];
         }
 
         return view('admin.user.info', [
             'levels' => Level::orderBy('level')->get(),
             'userGroups' => UserGroup::orderBy('id')->get(),
-            'roles' => $roles,
+            'roles' => $roles ?? [],
         ]);
     }
 
@@ -173,15 +176,13 @@ class UserController extends Controller
             $roles = Role::all()->pluck('description', 'name');
         } elseif (Auth::getUser()->hasPermissionTo('give roles')) {
             $roles = Auth::getUser()->roles();
-        } else {
-            $roles = [];
         }
 
         return view('admin.user.info', [
             'user' => $user->load('inviter:id,email'),
             'levels' => Level::orderBy('level')->get(),
             'userGroups' => UserGroup::orderBy('id')->get(),
-            'roles' => $roles,
+            'roles' => $roles ?? [],
         ]);
     }
 
@@ -256,38 +257,26 @@ class UserController extends Controller
     }
 
     // 批量生成账号
-    public function batchAddUsers(Request $request)
+    public function batchAddUsers()
     {
-        try {
-            DB::beginTransaction();
-
-            for ($i = 0; $i < $request->input('amount', 1); $i++) {
-                $uid = Helpers::addUser(Str::random(8).'@auto.generate', Str::random(), 1024 * GB, 365);
+        $preset = ['transfer_enable' => 1024 * GB, 'expired_at' => date('Y-m-d', strtotime('+365 days'))];
 
-                if ($uid) {
-                    // 写入用户流量变动记录
-                    Helpers::addUserTrafficModifyLog($uid, null, 0, 1024 * GB, '后台批量生成用户');
-                }
+        try {
+            for ($i = 0; $i < (int) request('amount', 1); $i++) {
+                $user = factory(User::class)->create($preset);
+                // 写入用户流量变动记录
+                Helpers::addUserTrafficModifyLog($user->id, null, 0, 1024 * GB, '后台批量生成用户');
             }
 
-            DB::commit();
-
             return Response::json(['status' => 'success', 'message' => '批量生成账号成功']);
         } catch (Exception $e) {
-            DB::rollBack();
-
             return Response::json(['status' => 'fail', 'message' => '批量生成账号失败:'.$e->getMessage()]);
         }
     }
 
     // 转换成某个用户的身份
-    public function switchToUser(Request $request): JsonResponse
+    public function switchToUser(User $user): JsonResponse
     {
-        $user = User::find($request->input('user_id'));
-        if (! $user) {
-            return Response::json(['status' => 'fail', 'message' => '用户不存在']);
-        }
-
         // 存储当前管理员ID,并将当前登录信息改成要切换的用户的身份信息
         Session::put('admin', Auth::id());
         Session::put('user', $user->id);
@@ -296,10 +285,10 @@ class UserController extends Controller
     }
 
     // 重置用户流量
-    public function resetTraffic(Request $request): JsonResponse
+    public function resetTraffic(User $user): JsonResponse
     {
         try {
-            User::find($request->input('id'))->update(['u' => 0, 'd' => 0]);
+            $user->update(['u' => 0, 'd' => 0]);
         } catch (Exception $e) {
             Log::error('流量重置失败:'.$e->getMessage());
 
@@ -310,19 +299,17 @@ class UserController extends Controller
     }
 
     // 操作用户余额
-    public function handleUserCredit(Request $request): JsonResponse
+    public function handleUserCredit(Request $request, User $user): JsonResponse
     {
-        $userId = $request->input('user_id');
-        $amount = $request->input('amount');
+        $amount = (int) $request->input('amount');
 
-        if (empty($userId) || empty($amount)) {
+        if (empty($amount)) {
             return Response::json(['status' => 'fail', 'message' => '充值异常']);
         }
-        $user = User::find($userId);
 
         // 加减余额
         if ($user->updateCredit($amount)) {
-            Helpers::addUserCreditLog($userId, null, $user->credit, $user->credit + $amount, $amount, '后台手动充值');  // 写入余额变动日志
+            Helpers::addUserCreditLog($user->id, null, $user->credit, $user->credit + $amount, $amount, '后台手动充值');  // 写入余额变动日志
 
             return Response::json(['status' => 'success', 'message' => '充值成功']);
         }
@@ -331,19 +318,15 @@ class UserController extends Controller
     }
 
     // 导出配置信息
-    public function export(Request $request, User $user)
+    public function export(User $user)
     {
-        if ($user === null) {
-            return Redirect::back();
-        }
-
-        $view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->orderBy('id')->paginate(15)->appends($request->except('page'));
-        $view['user'] = $user;
-
-        return view('admin.user.export', $view);
+        return view('admin.user.export', [
+            'user' => $user,
+            'nodeList' => Node::whereStatus(1)->orderByDesc('sort')->orderBy('id')->paginate(15)->appends(\request('page')),
+        ]);
     }
 
-    public function exportProxyConfig(Request $request, $uid): JsonResponse
+    public function exportProxyConfig(Request $request, User $user): JsonResponse
     {
         $node = Node::find($request->input('id'));
         if ($node->type === 1) {
@@ -356,7 +339,7 @@ class UserController extends Controller
             $proxyType = 'V2Ray';
         }
 
-        $data = $this->getUserNodeInfo($uid, $node->id, $request->input('type') !== 'text' ? 0 : 1);
+        $data = $this->getUserNodeInfo($user->id, $node->id, $request->input('type') !== 'text' ? 0 : 1);
 
         return Response::json(['status' => 'success', 'data' => $data, 'title' => $proxyType]);
     }

+ 23 - 44
app/Http/Controllers/Admin/UserGroupController.php

@@ -3,92 +3,71 @@
 namespace App\Http\Controllers\Admin;
 
 use App\Http\Controllers\Controller;
+use App\Http\Requests\Admin\UserGroupRequest;
 use App\Models\Node;
-use App\Models\User;
 use App\Models\UserGroup;
 use Exception;
-use Illuminate\Http\JsonResponse;
-use Illuminate\Http\RedirectResponse;
-use Illuminate\Http\Request;
-use Redirect;
-use Response;
-use Validator;
 
 class UserGroupController extends Controller
 {
-    public function index(Request $request)
+    public function index()
     {
-        $view['list'] = UserGroup::paginate(15)->appends($request->except('page'));
-
-        return view('admin.user.group.index', $view);
+        return view('admin.user.group.index', ['groups' => UserGroup::paginate(15)->appends(request('page'))]);
     }
 
     // 添加用户分组页面
     public function create()
     {
-        $nodes = Node::whereStatus(1)->pluck('name', 'id');
-
-        return view('admin.user.group.info', compact('nodes'));
+        return view('admin.user.group.info', ['nodes' => Node::whereStatus(1)->pluck('name', 'id')]);
     }
 
     // 添加用户分组
-    public function store(Request $request): RedirectResponse
+    public function store(UserGroupRequest $request)
     {
-        $validator = Validator::make($request->all(), ['name' => 'required']);
-
-        if ($validator->fails()) {
-            return Redirect::back()->withInput()->withErrors($validator->errors());
-        }
+        if ($userGroup = UserGroup::create($request->only(['name']))) {
+            $userGroup->nodes()->attach($request->input('nodes'));
 
-        $userGroup = UserGroup::create(['name' => $request->input('name'), 'nodes' => $request->input('nodes')]);
-
-        if ($userGroup) {
-            return Redirect::route('admin.user.group.edit', $userGroup)->with('successMsg', '操作成功');
+            return redirect(route('admin.user.group.edit', $userGroup))->with('successMsg', '操作成功');
         }
 
-        return Redirect::back()->withInput()->withErrors('操作失败');
+        return redirect()->back()->withInput()->withErrors('操作失败');
     }
 
     // 编辑用户分组页面
     public function edit(UserGroup $group)
     {
-        $nodes = Node::whereStatus(1)->pluck('name', 'id');
-
-        return view('admin.user.group.info', compact('group', 'nodes'));
+        return view('admin.user.group.info', [
+            'group' => $group,
+            'nodes' => Node::whereStatus(1)->pluck('name', 'id'),
+        ]);
     }
 
     // 编辑用户分组
-    public function update(Request $request, UserGroup $group)
+    public function update(UserGroupRequest $request, UserGroup $group)
     {
-        $validator = Validator::make($request->all(), ['name' => 'required']);
-
-        if ($validator->fails()) {
-            return Redirect::back()->withInput()->withErrors($validator->errors());
-        }
+        if ($group->update($request->only(['name']))) {
+            $group->nodes()->sync($request->input('nodes'));
 
-        $group->name = $request->input('name');
-        $group->nodes = $request->input('nodes');
-        if ($group->save()) {
-            return Redirect::back()->with('successMsg', '操作成功');
+            return redirect()->back()->with('successMsg', '操作成功');
         }
 
-        return Redirect::back()->withInput()->withErrors('操作失败');
+        return redirect()->back()->withInput()->withErrors('操作失败');
     }
 
     // 删除用户分组
-    public function destroy(UserGroup $group): JsonResponse
+    public function destroy(UserGroup $group)
     {
         // 校验该分组下是否存在关联账号
-        if (User::whereGroupId($group->id)->count()) {
-            return Response::json(['status' => 'fail', 'message' => '该分组下存在关联账号,请先取消关联!']);
+        if ($group->users->isNotEmpty()) {
+            return response()->json(['status' => 'fail', 'message' => '该分组下存在关联账号,请先取消关联!']);
         }
 
         try {
             $group->delete();
         } catch (Exception $e) {
-            return Response::json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
+            return response()->json(['status' => 'fail', 'message' => '删除失败,'.$e->getMessage()]);
         }
 
-        return Response::json(['status' => 'success', 'message' => '清理成功']);
+        return response()->json(['status' => 'success', 'message' => '清理成功']);
     }
 }

+ 40 - 53
app/Http/Controllers/AdminController.php

@@ -2,7 +2,6 @@
 
 namespace App\Http\Controllers;
 
-use App\Components\Helpers;
 use App\Models\Country;
 use App\Models\Invite;
 use App\Models\Label;
@@ -15,68 +14,56 @@ use App\Models\ReferralLog;
 use App\Models\SsConfig;
 use App\Models\User;
 use App\Models\UserHourlyDataFlow;
-use Auth;
-use Hash;
 use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Request;
 use Log;
 use PhpOffice\PhpSpreadsheet\Exception;
 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
-use Redirect;
 use Response;
 use Str;
 
-/**
- * 管理员控制器.
- *
- * Class AdminController
- */
 class AdminController extends Controller
 {
     public function index()
     {
         $past = strtotime('-'.sysConfig('expire_days').' days');
 
-        $view['expireDays'] = sysConfig('expire_days');
-        $view['totalUserCount'] = User::count(); // 总用户数
-        $view['todayRegister'] = User::whereDate('created_at', date('Y-m-d'))->count(); // 今日注册用户
-        $view['enableUserCount'] = User::whereEnable(1)->count(); // 有效用户数
-        $view['activeUserCount'] = User::where('t', '>=', $past)->count(); // 活跃用户数
-        $view['unActiveUserCount'] = User::whereEnable(1)->whereBetween('t', [1, $past])->count(); // 不活跃用户数
-        $view['onlineUserCount'] = User::where('t', '>=', strtotime('-10 minutes'))->count(); // 10分钟内在线用户数
-        $view['expireWarningUserCount'] = User::whereBetween('expired_at', [date('Y-m-d'), date('Y-m-d', strtotime('+'.sysConfig('expire_days').' days'))])->count(); // 临近过期用户数
-        $view['largeTrafficUserCount'] = User::whereRaw('(u + d)/transfer_enable >= 0.9')->where('status', '<>', -1)->count(); // 流量使用超过90%的用户
-        $view['flowAbnormalUserCount'] = count((new UserHourlyDataFlow)->trafficAbnormal()); // 1小时内流量异常用户
-        $view['nodeCount'] = Node::count();
-        $view['unnormalNodeCount'] = Node::whereStatus(0)->count();
-        $view['flowCount'] = flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d', strtotime('-30 days')))->sum('total'));
-        $view['todayFlowCount'] = flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d'))->sum('total'));
-        $view['totalFlowCount'] = flowAutoShow(NodeDailyDataFlow::sum('total'));
-        $view['totalCredit'] = User::where('credit', '<>', 0)->sum('credit') / 100;
-        $view['totalWaitRefAmount'] = ReferralLog::whereIn('status', [0, 1])->sum('commission') / 100;
-        $view['todayWaitRefAmount'] = ReferralLog::whereIn('status', [0, 1])->whereDate('created_at', date('Y-m-d'))->sum('commission') / 100;
-        $view['totalRefAmount'] = ReferralApply::whereStatus(2)->sum('amount') / 100;
-        $view['totalOrder'] = Order::count();
-        $view['todayOrder'] = Order::whereDate('created_at', date('Y-m-d'))->count();
-        $view['totalOnlinePayOrder'] = Order::where('pay_type', '<>', 0)->count();
-        $view['todayOnlinePayOrder'] = Order::where('pay_type', '<>', 0)->whereDate('created_at', date('Y-m-d'))->count();
-        $view['totalSuccessOrder'] = Order::whereStatus(2)->count();
-        $view['todaySuccessOrder'] = Order::whereStatus(2)->whereDate('created_at', date('Y-m-d'))->count();
-
-        return view('admin.index', $view);
+        return view('admin.index', [
+            'expireDays' => sysConfig('expire_days'),
+            'totalUserCount' => User::count(), // 总用户数
+            'todayRegister' => User::whereDate('created_at', date('Y-m-d'))->count(), // 今日注册用户
+            'enableUserCount' => User::whereEnable(1)->count(), // 有效用户数
+            'activeUserCount' => User::where('t', '>=', $past)->count(), // 活跃用户数,
+            'payingUserCount' => Order::whereStatus(2)->where('goods_id', '<>', 0)->whereIsExpire(0)->where('amount', '>', 0)->pluck('user_id')->unique()->count(), // 付费用户数
+            'unActiveUserCount' => User::whereEnable(1)->whereBetween('t', [1, $past])->count(), // 不活跃用户数
+            'onlineUserCount' => User::where('t', '>=', strtotime('-10 minutes'))->count(), // 10分钟内在线用户数
+            'expireWarningUserCount' => User::whereBetween('expired_at', [date('Y-m-d'), date('Y-m-d', strtotime('+'.sysConfig('expire_days').' days'))])->count(), // 临近过期用户数
+            'largeTrafficUserCount' => User::whereRaw('(u + d)/transfer_enable >= 0.9')->where('status', '<>', -1)->count(), // 流量使用超过90%的用户
+            'flowAbnormalUserCount' => count((new UserHourlyDataFlow)->trafficAbnormal()), // 1小时内流量异常用户
+            'nodeCount' => Node::count(),
+            'unnormalNodeCount' => Node::whereStatus(0)->count(),
+            'flowCount' => flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d', strtotime('-30 days')))->sum('total')),
+            'todayFlowCount' => flowAutoShow(NodeDailyDataFlow::where('created_at', '>=', date('Y-m-d'))->sum('total')),
+            'totalFlowCount' => flowAutoShow(NodeDailyDataFlow::sum('total')),
+            'totalCredit' => User::where('credit', '<>', 0)->sum('credit') / 100,
+            'totalWaitRefAmount' => ReferralLog::whereIn('status', [0, 1])->sum('commission') / 100,
+            'todayWaitRefAmount' => ReferralLog::whereIn('status', [0, 1])->whereDate('created_at', date('Y-m-d'))->sum('commission') / 100,
+            'totalRefAmount' => ReferralApply::whereStatus(2)->sum('amount') / 100,
+            'totalOrder' => Order::count(),
+            'todayOrder' => Order::whereDate('created_at', date('Y-m-d'))->count(),
+            'totalOnlinePayOrder' => Order::where('pay_type', '<>', 0)->count(),
+            'todayOnlinePayOrder' => Order::where('pay_type', '<>', 0)->whereDate('created_at', date('Y-m-d'))->count(),
+            'totalSuccessOrder' => Order::whereStatus(2)->count(),
+            'todaySuccessOrder' => Order::whereStatus(2)->whereDate('created_at', date('Y-m-d'))->count(),
+        ]);
     }
 
     // 邀请码列表
-    public function inviteList(Request $request)
+    public function inviteList()
     {
-        $view['inviteList'] = Invite::with(['invitee:id,email', 'inviter:id,email'])
-            ->orderBy('status')
-            ->orderByDesc('id')
-            ->paginate(15)
-            ->appends($request->except('page'));
-
-        return view('admin.inviteList', $view);
+        return view('admin.inviteList', [
+            'inviteList' => Invite::with(['invitee:id,email', 'inviter:id,email'])->orderBy('status')->orderByDesc('id')->paginate(15)->appends(request('page')),
+        ]);
     }
 
     // 生成邀请码
@@ -128,13 +115,13 @@ class AdminController extends Controller
 
     public function config()
     {
-        $view['methodList'] = SsConfig::type(1)->get();
-        $view['protocolList'] = SsConfig::type(2)->get();
-        $view['obfsList'] = SsConfig::type(3)->get();
-        $view['countryList'] = Country::all();
-        $view['levelList'] = Level::all();
-        $view['labelList'] = Label::with('nodes')->get();
-
-        return view('admin.config.config', $view);
+        return view('admin.config.config', [
+            'methods' => SsConfig::type(1)->get(),
+            'protocols' => SsConfig::type(2)->get(),
+            'obfsList' => SsConfig::type(3)->get(),
+            'countries' => Country::all(),
+            'levels' => Level::all(),
+            'labels' => Label::with('nodes')->get(),
+        ]);
     }
 }

+ 1 - 1
app/Http/Controllers/Api/Client/V1Controller.php

@@ -84,7 +84,7 @@ class V1Controller extends Controller
     public function nodeList(int $id = null)
     {
         $user = auth()->user();
-        $nodes = $user->userAccessNodes()->get();
+        $nodes = $user->nodes()->get();
         if (isset($id)) {
             $node = $nodes->where('id', $id)->first();
 

+ 14 - 24
app/Http/Controllers/Api/WebApi/BaseController.php

@@ -5,11 +5,8 @@ namespace App\Http\Controllers\Api\WebApi;
 use App\Components\Helpers;
 use App\Models\Node;
 use App\Models\NodeHeartBeat;
+use App\Models\NodeOnlineIp;
 use App\Models\NodeOnlineLog;
-use App\Models\NodeOnlineUserIp;
-use App\Models\Rule;
-use App\Models\RuleGroup;
-use App\Models\RuleGroupNode;
 use App\Models\RuleLog;
 use App\Models\User;
 use App\Models\UserDataFlowLog;
@@ -74,7 +71,7 @@ class BaseController
                 return $this->returnData('上报节点在线用户IP信息失败,请检查字段');
             }
 
-            $obj = new NodeOnlineUserIp();
+            $obj = new NodeOnlineIp();
             $obj->node_id = $id;
             $obj->user_id = $input['uid'];
             $obj->ip = $input['ip'];
@@ -137,27 +134,21 @@ class BaseController
     }
 
     // 获取节点的审计规则
-    public function getNodeRule($id): JsonResponse
+    public function getNodeRule(Node $node): JsonResponse
     {
-        $nodeRule = RuleGroupNode::whereNodeId($id)->first();
         $data = [];
         //节点未设置任何审计规则
-        if ($nodeRule) {
-            $ruleGroup = RuleGroup::find($nodeRule->rule_group_id);
-            if ($ruleGroup && $ruleGroup->rules) {
-                foreach ($ruleGroup->rules as $ruleId) {
-                    $rule = Rule::find($ruleId);
-                    if ($rule) {
-                        $data[] = [
-                            'id' => $rule->id,
-                            'type' => $rule->type_api_label,
-                            'pattern' => $rule->pattern,
-                        ];
-                    }
-                }
-
-                return $this->returnData('获取节点审计规则成功', 'success', 200, ['mode' => $ruleGroup->type ? 'reject' : 'allow', 'rules' => $data]);
+        if ($node->rule_group_id) {
+            $ruleGroup = $node->ruleGroup;
+            foreach ($ruleGroup->rules as $rule) {
+                $data[] = [
+                    'id' => $rule->id,
+                    'type' => $rule->type_api_label,
+                    'pattern' => $rule->pattern,
+                ];
             }
+
+            return $this->returnData('获取节点审计规则成功', 'success', 200, ['mode' => $ruleGroup->type ? 'reject' : 'allow', 'rules' => $data]);
         }
 
         //放行
@@ -173,9 +164,8 @@ class BaseController
             $obj->node_id = $id;
             $obj->rule_id = $request->input('rule_id');
             $obj->reason = $request->input('reason');
-            $obj->save();
 
-            if ($obj->id) {
+            if ($obj->save()) {
                 return $this->returnData('上报用户触发审计规则日志成功', 'success', 200);
             }
         }

+ 4 - 9
app/Http/Controllers/Api/WebApi/TrojanController.php

@@ -8,10 +8,8 @@ use Illuminate\Http\JsonResponse;
 class TrojanController extends BaseController
 {
     // 获取节点信息
-    public function getNodeInfo($id): JsonResponse
+    public function getNodeInfo(Node $node): JsonResponse
     {
-        $node = Node::find($id);
-
         return $this->returnData('获取节点信息成功', 'success', 200, [
             'id' => $node->id,
             'is_udp' => $node->is_udp ? true : false,
@@ -26,12 +24,9 @@ class TrojanController extends BaseController
     }
 
     // 获取节点可用的用户列表
-    public function getUserList($id): JsonResponse
+    public function getUserList(Node $node): JsonResponse
     {
-        $users = Node::find($id)->node_access_users;
-        $data = [];
-
-        foreach ($users as $user) {
+        foreach ($node->users() as $user) {
             $data[] = [
                 'uid' => $user->id,
                 'password' => $user->passwd,
@@ -39,6 +34,6 @@ class TrojanController extends BaseController
             ];
         }
 
-        return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]);
+        return $this->returnData('获取用户列表成功', 'success', 200, $data ?? [], ['updateTime' => time()]);
     }
 }

+ 11 - 30
app/Http/Controllers/Api/WebApi/V2RayController.php

@@ -5,15 +5,13 @@ namespace App\Http\Controllers\Api\WebApi;
 use App\Models\Node;
 use App\Models\NodeCertificate;
 use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Request;
 
 class V2RayController extends BaseController
 {
     // 获取节点信息
-    public function getNodeInfo($id): JsonResponse
+    public function getNodeInfo(Node $node): JsonResponse
     {
-        $node = Node::find($id);
-        $nodeDv = NodeCertificate::whereDomain($node->v2_host)->first();
+        $cert = NodeCertificate::whereDomain($node->v2_host)->first();
         $tlsProvider = $node->tls_provider ?: sysConfig('v2ray_tls_provider');
         if (! $tlsProvider) {
             $tlsProvider = null;
@@ -27,8 +25,8 @@ class V2RayController extends BaseController
             'push_port' => $node->push_port,
             'redirect_url' => (string) sysConfig('redirect_url'),
             'secret' => $node->auth->secret,
-            'key' => $nodeDv->key ?? '',
-            'pem' => $nodeDv->pem ?? '',
+            'key' => $cert->key ?? '',
+            'pem' => $cert->pem ?? '',
             'v2_license' => (string) sysConfig('v2ray_license'),
             'v2_alter_id' => $node->v2_alter_id,
             'v2_port' => $node->v2_port,
@@ -43,12 +41,9 @@ class V2RayController extends BaseController
     }
 
     // 获取节点可用的用户列表
-    public function getUserList($id): JsonResponse
+    public function getUserList(Node $node): JsonResponse
     {
-        $users = Node::find($id)->node_access_users;
-        $data = [];
-
-        foreach ($users as $user) {
+        foreach ($node->users() as $user) {
             $data[] = [
                 'uid' => $user->id,
                 'vmess_uid' => $user->vmess_id,
@@ -56,29 +51,15 @@ class V2RayController extends BaseController
             ];
         }
 
-        return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]);
+        return $this->returnData('获取用户列表成功', 'success', 200, $data ?? [], ['updateTime' => time()]);
     }
 
     // 上报节点伪装域名证书信息
-    public function addCertificate(Request $request, $id): JsonResponse
+    public function addCertificate(Node $node): JsonResponse
     {
-        $key = $request->input('key');
-        $pem = $request->input('pem');
-
-        if ($request->has(['key', 'pem'])) {
-            $node = Node::find($id);
-            $Dv = NodeCertificate::whereDomain($node->v2_host)->first();
-            if ($Dv) {
-                $ret = NodeCertificate::whereId($Dv->id)->update(['key' => $key, 'pem' => $pem]);
-            } else {
-                $ret = new NodeCertificate();
-                $ret->domain = $node->server;
-                $ret->key = $request->input('key');
-                $ret->pem = $request->input('pem');
-                $ret->save();
-            }
-
-            if ($ret) {
+        if (request()->has(['key', 'pem'])) {
+            $cert = NodeCertificate::whereDomain($node->v2_host)->firstOrCreate(['domain' => $node->server]);
+            if ($cert && $cert->update(['key' => request('key'), 'pem' => request('pem')])) {
                 return $this->returnData('上报节点伪装域名证书成功', 'success', 200);
             }
         }

+ 4 - 10
app/Http/Controllers/Api/WebApi/VNetController.php

@@ -8,10 +8,8 @@ use Illuminate\Http\JsonResponse;
 class VNetController extends BaseController
 {
     // 获取节点信息
-    public function getNodeInfo($id): JsonResponse
+    public function getNodeInfo(Node $node): JsonResponse
     {
-        $node = Node::find($id);
-
         return $this->returnData('获取节点信息成功', 'success', 200, [
             'id' => $node->id,
             'method' => $node->method,
@@ -31,13 +29,9 @@ class VNetController extends BaseController
     }
 
     // 获取节点可用的用户列表
-    public function getUserList($id): JsonResponse
+    public function getUserList(Node $node): JsonResponse
     {
-        $node = Node::find($id);
-        $users = $node->node_access_users;
-        $data = [];
-
-        foreach ($users as $user) {
+        foreach ($node->users() as $user) {
             $data[] = [
                 'uid' => $user->id,
                 'port' => $user->port,
@@ -51,7 +45,7 @@ class VNetController extends BaseController
             ];
         }
 
-        if ($data) {
+        if (isset($data)) {
             return $this->returnData('获取用户列表成功', 'success', 200, $data, ['updateTime' => time()]);
         }
 

+ 18 - 34
app/Http/Controllers/AuthController.php

@@ -51,10 +51,6 @@ class AuthController extends Controller
                 return Redirect::back()->withInput()->withErrors($validator->errors());
             }
 
-            $email = $request->input('email');
-            $password = $request->input('password');
-            $remember = $request->input('remember');
-
             // 是否校验验证码
             $captcha = $this->check_captcha($request);
             if ($captcha !== false) {
@@ -62,7 +58,7 @@ class AuthController extends Controller
             }
 
             // 验证账号并创建会话
-            if (! Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
+            if (! Auth::attempt($validator->validated(), $request->input('remember'))) {
                 return Redirect::back()->withInput()->withErrors(trans('auth.login_error'));
             }
             $user = Auth::getUser();
@@ -81,23 +77,17 @@ class AuthController extends Controller
             if ($user->status === 0 && sysConfig('is_activate_account')) {
                 Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
 
-                return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'<a href="'.route('active').'?email='.$email.'" target="_blank"><span style="color:#000">【'.trans('auth.active_account').'】</span></a>');
+                return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'<a href="'.route('active').'?email='.$user->email.'" target="_blank"><span style="color:#000">【'.trans('auth.active_account').'】</span></a>');
             }
 
             // 写入登录日志
             $this->addUserLoginLog($user->id, IP::getClientIp());
 
             // 更新登录信息
-            Auth::getUser()->update(['last_login' => time()]);
-
-            // 根据权限跳转
-            if ($user->hasPermissionTo('admin.index')) {
-                return Redirect::route('admin.index');
-            }
-
-            return Redirect::route('home');
+            $user->update(['last_login' => time()]);
         }
 
+        // 根据权限跳转
         if (Auth::check()) {
             if (Auth::getUser()->hasPermissionTo('admin.index')) {
                 return Redirect::route('admin.index');
@@ -110,7 +100,7 @@ class AuthController extends Controller
     }
 
     // 校验验证码
-    private function check_captcha($request)
+    private function check_captcha(Request $request)
     {
         switch (sysConfig('is_captcha')) {
             case 1: // 默认图形验证码
@@ -298,14 +288,14 @@ class AuthController extends Controller
             $transfer_enable = MB * ((int) sysConfig('default_traffic') + ($inviter_id ? (int) sysConfig('referral_traffic') : 0));
 
             // 创建新用户
-            $uid = Helpers::addUser($email, $password, $transfer_enable, sysConfig('default_days'), $inviter_id);
+            $user = factory(User::class)->create([
+                'username' => $username, 'email' => $email, 'password' => $password, 'transfer_enable' => $transfer_enable, 'inviter_id' => $inviter_id,
+            ]);
 
             // 注册失败,抛出异常
-            if (! $uid) {
+            if (! $user) {
                 return Redirect::back()->withInput()->withErrors(trans('auth.register_fail'));
             }
-            // 更新昵称
-            User::find($uid)->update(['username' => $username]);
 
             // 注册次数+1
             if (Cache::has($cacheKey)) {
@@ -316,16 +306,16 @@ class AuthController extends Controller
 
             // 更新邀请码
             if ($affArr['code_id'] && sysConfig('is_invite_register')) {
-                Invite::find($affArr['code_id'])->update(['invitee_id' => $uid, 'status' => 1]);
+                Invite::find($affArr['code_id'])->update(['invitee_id' => $user->id, 'status' => 1]);
             }
 
             // 清除邀请人Cookie
             Cookie::unqueue('register_aff');
 
             // 注册后发送激活码
-            if (sysConfig('is_activate_account') == 2) {
+            if ((int) sysConfig('is_activate_account') === 2) {
                 // 生成激活账号的地址
-                $token = $this->addVerifyUrl($uid, $email);
+                $token = $this->addVerifyUrl($user->id, $email);
                 $activeUserUrl = route('activeAccount', $token);
 
                 $logId = Helpers::addNotificationLog('注册激活', '请求地址:'.$activeUserUrl, 1, $email);
@@ -341,8 +331,8 @@ class AuthController extends Controller
                     }
                 }
 
-                if (sysConfig('is_activate_account') == 1) {
-                    User::find($uid)->update(['status' => 1]);
+                if ((int) sysConfig('is_activate_account') === 1) {
+                    $user->update(['status' => 1]);
                 }
 
                 Session::flash('successMsg', trans('auth.register_success'));
@@ -351,10 +341,9 @@ class AuthController extends Controller
             return Redirect::route('login')->withInput();
         }
 
-        $view['emailList'] = sysConfig('is_email_filtering') != 2 ? false : EmailFilter::whereType(2)->get();
         Session::put('register_token', Str::random());
 
-        return view('auth.register', $view);
+        return view('auth.register', ['emailList' => (int) sysConfig('is_email_filtering') !== 2 ? false : EmailFilter::whereType(2)->get()]);
     }
 
     //邮箱检查
@@ -562,10 +551,7 @@ class AuthController extends Controller
             $verify->save();
         }
 
-        // 重新获取一遍verify
-        $view['verify'] = Verify::type(1)->whereToken($token)->first();
-
-        return view('auth.reset', $view);
+        return view('auth.reset', ['verify' => Verify::type(1)->whereToken($token)->first()]); // 重新获取一遍verify
     }
 
     // 激活账号页
@@ -744,13 +730,11 @@ class AuthController extends Controller
     // 公开的邀请码列表
     public function free()
     {
-        $view['inviteList'] = Invite::whereInviterId(null)->whereStatus(0)->paginate();
-
-        return view('auth.free', $view);
+        return view('auth.free', ['inviteList' => Invite::whereInviterId(null)->whereStatus(0)->paginate()]);
     }
 
     // 切换语言
-    public function switchLang($locale): RedirectResponse
+    public function switchLang(string $locale): RedirectResponse
     {
         Session::put('locale', $locale);
 

+ 25 - 31
app/Http/Controllers/PaymentController.php

@@ -95,7 +95,6 @@ class PaymentController extends Controller
         $pay_type = $request->input('pay_type');
         $amount = 0;
 
-        $goods = Goods::find($goods_id);
         // 充值余额
         if ($credit) {
             if (! is_numeric($credit) || $credit <= 0) {
@@ -104,6 +103,7 @@ class PaymentController extends Controller
             $amount = $credit;
         // 购买服务
         } elseif ($goods_id && self::$method) {
+            $goods = Goods::find($goods_id);
             if (! $goods || ! $goods->status) {
                 return Response::json(['status' => 'fail', 'message' => '订单创建失败:商品已下架']);
             }
@@ -140,7 +140,7 @@ class PaymentController extends Controller
                 }
             }
 
-            // 使用优惠券 TODO 代码整合至 CouponService
+            // 使用优惠券
             if ($coupon_sn) {
                 $coupon = Coupon::whereStatus(0)->whereIn('type', [1, 2])->whereSn($coupon_sn)->first();
                 if (! $coupon) {
@@ -162,31 +162,29 @@ class PaymentController extends Controller
             }
         }
 
-        $orderSn = date('ymdHis').random_int(100000, 999999);
-
         // 生成订单
         try {
-            $order = new Order();
-            $order->order_sn = $orderSn;
-            $order->user_id = Auth::id();
-            $order->goods_id = $credit ? 0 : $goods_id;
-            $order->coupon_id = $coupon->id ?? 0;
-            $order->origin_amount = $credit ?: $goods->price;
-            $order->amount = $amount;
-            $order->pay_type = $pay_type;
-            $order->pay_way = self::$method;
-            $order->save();
+            $newOrder = Order::create([
+                'order_sn' => date('ymdHis').random_int(100000, 999999),
+                'user_id' => auth()->id(),
+                'goods_id' => $credit ? null : $goods_id,
+                'coupon_id' => $coupon->id ?? null,
+                'origin_amount' => $credit ?: $goods->price ?? 0,
+                'amount'=>$amount,
+                'pay_type'=>$pay_type,
+                'pay_way'=>self::$method,
+            ]);
 
             // 使用优惠券,减少可使用次数
             if (! empty($coupon)) {
                 if ($coupon->usable_times > 0) {
-                    Coupon::whereId($coupon->id)->decrement('usable_times', 1);
+                    $coupon->decrement('usable_times', 1);
                 }
 
-                Helpers::addCouponLog('订单支付使用', $coupon->id, $goods_id, $order->id);
+                Helpers::addCouponLog('订单支付使用', $coupon->id, $goods_id, $newOrder->id);
             }
 
-            $request->merge(['id' => $order->id, 'type' => $pay_type, 'amount' => $amount]);
+            $request->merge(['id' => $newOrder->id, 'type' => $pay_type, 'amount' => $amount]);
 
             // 生成支付单
             return self::getClient()->purchase($request);
@@ -197,15 +195,10 @@ class PaymentController extends Controller
         return Response::json(['status' => 'fail', 'message' => '订单创建失败']);
     }
 
-    public function close(Request $request): JsonResponse
+    public function close(Order $order): JsonResponse
     {
-        $order = Order::find($request->input('id'));
-        if ($order) {
-            if (! $order->update(['status' => -1])) {
-                return Response::json(['status' => 'fail', 'message' => '关闭订单失败']);
-            }
-        } else {
-            return Response::json(['status' => 'fail', 'message' => '未找到订单']);
+        if (! $order->update(['status' => -1])) {
+            return Response::json(['status' => 'fail', 'message' => '关闭订单失败']);
         }
 
         return Response::json(['status' => 'success', 'message' => '关闭订单成功']);
@@ -215,13 +208,14 @@ class PaymentController extends Controller
     public function detail($trade_no)
     {
         $payment = Payment::uid()->with(['order', 'order.goods'])->whereTradeNo($trade_no)->firstOrFail();
-        $view['payment'] = $payment;
         $goods = $payment->order->goods;
-        $view['name'] = $goods->name ?? '余额充值';
-        $view['days'] = $goods->days ?? 0;
-        $view['pay_type'] = $payment->order->pay_type_label ?: 0;
-        $view['pay_type_icon'] = $payment->order->pay_type_icon;
 
-        return view('user.payment', $view);
+        return view('user.payment', [
+            'payment' => $payment,
+            'name' => $goods->name ?? '余额充值',
+            'days' => $goods->days ?? 0,
+            'pay_type' => $payment->order->pay_type_label ?: 0,
+            'pay_type_icon' => $payment->order->pay_type_icon,
+        ]);
     }
 }

+ 11 - 10
app/Http/Controllers/User/AffiliateController.php

@@ -18,17 +18,18 @@ class AffiliateController extends Controller
         if (ReferralLog::uid()->doesntExist() && Order::uid()->whereStatus(2)->doesntExist()) {
             return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 <a class="btn btn-sm btn-danger" href="/">返 回</a>'], 402);
         }
-        $view['referral_traffic'] = flowAutoShow(sysConfig('referral_traffic') * MB);
-        $view['referral_percent'] = sysConfig('referral_percent');
-        $view['referral_money'] = sysConfig('referral_money');
-        $view['totalAmount'] = ReferralLog::uid()->sum('commission') / 100;
-        $view['canAmount'] = ReferralLog::uid()->whereStatus(0)->sum('commission') / 100;
-        $view['aff_link'] = route('register', ['aff' => Auth::id()]);
-        $view['referralLogList'] = ReferralLog::uid()->with('invitee:id,email')->latest()->paginate(10, ['*'], 'log_page');
-        $view['referralApplyList'] = ReferralApply::uid()->latest()->paginate(10, ['*'], 'apply_page');
-        $view['referralUserList'] = Auth::getUser()->invitees()->select(['email', 'created_at'])->latest()->paginate(10, ['*'], 'user_page');
 
-        return view('user.referral', $view);
+        return view('user.referral', [
+            'referral_traffic' => flowAutoShow(sysConfig('referral_traffic') * MB),
+            'referral_percent' => sysConfig('referral_percent'),
+            'referral_money' => sysConfig('referral_money'),
+            'totalAmount' => ReferralLog::uid()->sum('commission') / 100,
+            'canAmount' => ReferralLog::uid()->whereStatus(0)->sum('commission') / 100,
+            'aff_link' => route('register', ['aff' => Auth::id()]),
+            'referralLogList' => ReferralLog::uid()->with('invitee:id,email')->latest()->paginate(10, ['*'], 'log_page'),
+            'referralApplyList' => ReferralApply::uid()->latest()->paginate(10, ['*'], 'apply_page'),
+            'referralUserList' => Auth::getUser()->invitees()->select(['email', 'created_at'])->latest()->paginate(10, ['*'], 'user_page'),
+        ]);
     }
 
     // 申请提现

+ 1 - 1
app/Http/Controllers/User/SubscribeController.php

@@ -77,7 +77,7 @@ class SubscribeController extends Controller
         $this->subscribeLog($subscribe->id, IP::getClientIp(), $request->headers);
 
         // 获取这个账号可用节点
-        $query = $user->whereIsSubscribe(1)->userAccessNodes();
+        $query = $user->whereIsSubscribe(1)->nodes();
 
         if ($this->subType === 1) {
             $query = $query->whereIn('type', [1, 4]);

+ 87 - 115
app/Http/Controllers/UserController.php

@@ -16,9 +16,6 @@ use App\Models\NodePing;
 use App\Models\Order;
 use App\Models\Ticket;
 use App\Models\TicketReply;
-use App\Models\UserLoginLog;
-use App\Models\UserSubscribe;
-use Auth;
 use Cache;
 use DB;
 use Exception;
@@ -34,38 +31,22 @@ use Session;
 use Str;
 use Validator;
 
-/**
- * 用户控制器.
- *
- * Class UserController
- */
 class UserController extends Controller
 {
     public function index()
     {
+        // 用户转换
         if (Session::has('user')) {
-            Auth::loginUsingId(Session::get('user'));
+            auth()->loginUsingId(Session::get('user'));
             Session::forget('user');
         }
-        $user = Auth::getUser();
+        $user = auth()->user();
         $totalTransfer = $user->transfer_enable;
         $usedTransfer = $user->usedTraffic();
         $unusedTraffic = $totalTransfer - $usedTransfer > 0 ? $totalTransfer - $usedTransfer : 0;
         $expireTime = $user->expired_at;
-        $view['remainDays'] = $expireTime < date('Y-m-d') ? -1 : Helpers::daysToNow($expireTime);
-        $view['resetDays'] = $user->reset_time ? Helpers::daysToNow($user->reset_time) : 0;
-        $view['unusedTraffic'] = flowAutoShow($unusedTraffic);
-        $view['expireTime'] = $expireTime;
-        $view['banedTime'] = $user->ban_time ?: 0;
-        $view['unusedPercent'] = $totalTransfer > 0 ? round($unusedTraffic / $totalTransfer, 2) * 100 : 0;
-        $view['announcements'] = Article::type(2)->take(5)->latest()->Paginate(1); // 公告
-        //流量异常判断
-        $view['isTrafficWarning'] = $user->isTrafficWarning();
-        //付费用户判断
-        $view['paying_user'] = $user->activePayingUser();
-        $view['userLoginLog'] = UserLoginLog::whereUserId($user->id)->latest()->first(); // 近期登录日志
-
-        $nodes = $user->userAccessNodes()->get();
+
+        $nodes = $user->nodes()->get();
         $subType = [];
         if ($nodes->whereIn('type', [1, 4])->isNotEmpty()) {
             $subType[] = 'ss';
@@ -77,18 +58,27 @@ class UserController extends Controller
             $subType[] = 'trojan';
         }
 
-        $view['subscribe_status'] = $user->subscribe->status;
-        $view['subType'] = $subType;
-        $view['subUrl'] = route('sub', $user->subscribe->code);
-        $view = array_merge($view, $this->dataFlowChart($user->id));
-
-        return view('user.index', $view);
+        return view('user.index', array_merge([
+            'remainDays' => $expireTime < date('Y-m-d') ? -1 : Helpers::daysToNow($expireTime),
+            'resetDays' => $user->reset_time ? Helpers::daysToNow($user->reset_time) : 0,
+            'unusedTraffic' => flowAutoShow($unusedTraffic),
+            'expireTime' => $expireTime,
+            'banedTime' => $user->ban_time ?: 0,
+            'unusedPercent' => $totalTransfer > 0 ? round($unusedTraffic / $totalTransfer, 2) * 100 : 0,
+            'announcements' => Article::type(2)->take(5)->latest()->Paginate(1), // 公告
+            'isTrafficWarning' => $user->isTrafficWarning(), // 流量异常判断
+            'paying_user' => $user->activePayingUser(), // 付费用户判断
+            'userLoginLog' => $user->loginLogs()->latest()->first(), // 近期登录日志
+            'subscribe_status' => $user->subscribe->status,
+            'subType' => $subType,
+            'subUrl' => route('sub', $user->subscribe->code),
+        ], $this->dataFlowChart($user->id)));
     }
 
     // 签到
     public function checkIn(): JsonResponse
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         // 系统开启登录加积分功能才可以签到
         if (! sysConfig('is_checkin')) {
             return Response::json(['status' => 'fail', 'message' => '系统未开启签到功能']);
@@ -118,7 +108,7 @@ class UserController extends Controller
     // 节点列表
     public function nodeList(Request $request)
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         if ($request->isMethod('POST')) {
             $infoType = $request->input('type');
 
@@ -135,9 +125,7 @@ class UserController extends Controller
         }
 
         // 获取当前用户可用节点
-        $nodeList = $user->userAccessNodes()->with(['labels', 'level_table'])->get();
-
-        $view['nodesGeo'] = $nodeList->pluck('name', 'geo')->toArray();
+        $nodeList = $user->nodes()->with(['labels', 'level_table'])->get();
         $onlineNode = NodeHeartBeat::recently()->distinct()->pluck('node_id')->toArray();
         $pingNodeLogs = NodePing::whereMonth('created_at', date('m'))->get(['node_id', 'ct', 'cu', 'cm', 'hk']);
         foreach ($nodeList as $node) {
@@ -150,23 +138,23 @@ class UserController extends Controller
             // 节点在线状态
             $node->offline = ! in_array($node->id, $onlineNode, true);
         }
-        $view['nodeList'] = $nodeList ?? [];
 
-        return view('user.nodeList', $view);
+        return view('user.nodeList', [
+            'nodesGeo' => $nodeList->pluck('name', 'geo')->toArray(),
+            'nodeList' => $nodeList,
+        ]);
     }
 
     // 公告详情
-    public function article(Request $request)
+    public function article(Article $article)
     {
-        $view['info'] = Article::findOrFail($request->input('id'));
-
-        return view('user.article', $view);
+        return view('user.article', compact($article));
     }
 
     // 修改个人资料
     public function profile(Request $request)
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         if ($request->isMethod('POST')) {
             $old_password = $request->input('old_password');
             $new_password = $request->input('new_password');
@@ -224,30 +212,26 @@ class UserController extends Controller
     // 商品列表
     public function services(Request $request)
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         // 余额充值商品,只取10个
-        $view['chargeGoodsList'] = Goods::type(3)->whereStatus(1)->orderBy('price')->limit(10)->get();
-        $view['goodsList'] = Goods::whereStatus(1)
-            ->where('type', '<=', '2')
-            ->orderByDesc('type')
-            ->orderByDesc('sort')
-            ->paginate(10)
-            ->appends($request->except('page'));
         $renewOrder = Order::userActivePlan($user->id)->first();
         $renewPrice = $renewOrder->goods ?? 0;
-        $view['renewTraffic'] = $renewPrice->renew ?? 0;
         // 有重置日时按照重置日为标准,否者就以过期日为标准
         $dataPlusDays = $user->reset_time ?? $user->expired_at;
-        $view['dataPlusDays'] = $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0;
 
-        return view('user.services', $view);
+        return view('user.services', [
+            'chargeGoodsList' => Goods::type(3)->whereStatus(1)->orderBy('price')->limit(10)->get(),
+            'goodsList' => Goods::whereStatus(1)->where('type', '<=', '2')->orderByDesc('type')->orderByDesc('sort')->paginate(10)->appends($request->except('page')),
+            'renewTraffic' => $renewPrice->renew ?? 0,
+            'dataPlusDays' => $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0,
+        ]);
     }
 
     //重置流量
     public function resetUserTraffic(): ?JsonResponse
     {
-        $user = Auth::getUser();
-        $order = Order::userActivePlan()->first();
+        $user = auth()->user();
+        $order = Order::userActivePlan()->firstOrFail();
         $renewCost = $order->goods->renew;
         if ($user->credit < $renewCost) {
             return Response::json(['status' => 'fail', 'message' => '余额不足,请充值余额']);
@@ -268,26 +252,22 @@ class UserController extends Controller
     public function ticketList(Request $request)
     {
         return view('user.ticketList', [
-            'tickets' => Auth::user()->tickets()->latest()->paginate(10)->appends($request->except('page')),
+            'tickets' => auth()->user()->tickets()->latest()->paginate(10)->appends($request->except('page')),
         ]);
     }
 
     // 订单
     public function invoices(Request $request)
     {
-        $view['orderList'] = Auth::user()->orders()
-            ->with(['goods', 'payment'])
-            ->orderByDesc('id')
-            ->paginate(10)
-            ->appends($request->except('page'));
-        $view['prepaidPlan'] = Order::userPrepay()->exists();
-
-        return view('user.invoices', $view);
+        return view('user.invoices', [
+            'orderList' => auth()->user()->orders()->with(['goods', 'payment'])->orderByDesc('id')->paginate(10)->appends($request->except('page')),
+            'prepaidPlan' => Order::userPrepay()->exists(),
+        ]);
     }
 
     public function closePlan(): JsonResponse
     {
-        $activePlan = Order::userActivePlan()->first();
+        $activePlan = Order::userActivePlan()->firstOrFail();
         $activePlan->is_expire = 1;
 
         if ($activePlan->save()) {
@@ -305,15 +285,13 @@ class UserController extends Controller
     // 订单明细
     public function invoiceDetail($sn)
     {
-        $view['order'] = Order::uid()->whereOrderSn($sn)->with(['goods', 'coupon', 'payment'])->firstOrFail();
-
-        return view('user.invoiceDetail', $view);
+        return view('user.invoiceDetail', ['order' => Order::uid()->whereOrderSn($sn)->with(['goods', 'coupon', 'payment'])->firstOrFail()]);
     }
 
     // 添加工单
     public function createTicket(Request $request): ?JsonResponse
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         $title = $request->input('title');
         $content = clean($request->input('content'));
         $content = str_replace(['atob', 'eval'], '', $content);
@@ -367,7 +345,7 @@ class UserController extends Controller
 
             $obj = new TicketReply();
             $obj->ticket_id = $id;
-            $obj->user_id = Auth::id();
+            $obj->user_id = auth()->user()->id;
             $obj->content = $content;
 
             if ($obj->save()) {
@@ -392,10 +370,10 @@ class UserController extends Controller
             return Response::json(['status' => 'fail', 'message' => '回复失败']);
         }
 
-        $view['ticket'] = $ticket;
-        $view['replyList'] = TicketReply::whereTicketId($id)->with('user')->oldest()->get();
-
-        return view('user.replyTicket', $view);
+        return view('user.replyTicket', [
+            'ticket' => $ticket,
+            'replyList' => $ticket->reply()->with('user')->oldest()->get(),
+        ]);
     }
 
     // 关闭工单
@@ -423,18 +401,18 @@ class UserController extends Controller
             );
         }
 
-        $view['num'] = Auth::getUser()->invite_num; // 还可以生成的邀请码数量
-        $view['inviteList'] = Invite::uid()->with(['invitee', 'inviter'])->paginate(10); // 邀请码列表
-        $view['referral_traffic'] = flowAutoShow(sysConfig('referral_traffic') * MB);
-        $view['referral_percent'] = sysConfig('referral_percent');
-
-        return view('user.invite', $view);
+        return view('user.invite', [
+            'num' => auth()->user()->invite_num, // 还可以生成的邀请码数量
+            'inviteList' => Invite::uid()->with(['invitee', 'inviter'])->paginate(10), // 邀请码列表
+            'referral_traffic' => flowAutoShow(sysConfig('referral_traffic') * MB),
+            'referral_percent' => sysConfig('referral_percent'),
+        ]);
     }
 
     // 生成邀请码
     public function makeInvite(): JsonResponse
     {
-        $user = Auth::getUser();
+        $user = auth()->user();
         if ($user->invite_num <= 0) {
             return Response::json(['status' => 'fail', 'message' => '生成失败:已无邀请码生成名额']);
         }
@@ -483,7 +461,7 @@ class UserController extends Controller
             return Response::json(['status' => 'fail', 'title' => '抱歉', 'message' => '优惠券已失效!']);
         }
 
-        if ($coupon->start_time > time()) {
+        if ($coupon->start_time > date('Y-m-d H:i:s')) {
             return Response::json(['status' => 'fail', 'title' => '优惠券尚未生效', 'message' => '请等待活动正式开启']);
         }
 
@@ -501,20 +479,17 @@ class UserController extends Controller
     }
 
     // 购买服务
-    public function buy($goods_id)
+    public function buy(Goods $good)
     {
-        $user = Auth::getUser();
-        $goods = Goods::whereId($goods_id)->whereStatus(1)->first();
-        if (empty($goods)) {
-            return Redirect::route('shop');
-        }
+        $user = auth()->user();
         // 有重置日时按照重置日为标准,否者就以过期日为标准
         $dataPlusDays = $user->reset_time ?? $user->expired_at;
-        $view['dataPlusDays'] = $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0;
-        $view['activePlan'] = Order::userActivePlan()->exists();
-        $view['goods'] = $goods;
 
-        return view('user.buy', $view);
+        return view('user.buy', [
+            'dataPlusDays' => $dataPlusDays > date('Y-m-d') ? Helpers::daysToNow($dataPlusDays) : 0,
+            'activePlan' => Order::userActivePlan()->exists(),
+            'goods' => $good,
+        ]);
     }
 
     // 帮助中心
@@ -533,25 +508,22 @@ class UserController extends Controller
             $data[] = 'trojan';
         }
 
-        $view['sub'] = $data;
-
-        //付费用户判断
-        $view['paying_user'] = Auth::user()->activePayingUser();
-        //客户端安装
-        $view['Shadowrocket_install'] = 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Shadowrocket.plist';
-        $view['Quantumult_install'] = 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Quantumult.plist';
-        // 订阅连接
-        $subscribe = UserSubscribe::whereUserId(Auth::id())->firstOrFail();
-        $view['subscribe_status'] = $subscribe->status;
+        $subscribe = auth()->user()->subscribe;
         $subscribe_link = route('sub', $subscribe->code);
-        $view['link'] = $subscribe_link;
-        $view['subscribe_link'] = 'sub://'.base64url_encode($subscribe_link);
-        $view['Shadowrocket_link'] = 'shadowrocket://add/sub://'.base64url_encode($subscribe_link).'?remarks='.(sysConfig('website_name').'-'.sysConfig('website_url'));
-        $view['Shadowrocket_linkQrcode'] = 'sub://'.base64url_encode($subscribe_link).'#'.base64url_encode(sysConfig('website_name'));
-        $view['Quantumult_linkOut'] = 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Pro.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf');
-        $view['Quantumult_linkIn'] = 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/BacktoCN.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf');
-
-        return view('user.help', $view);
+
+        return view('user.help', [
+            'sub' => $data,
+            'paying_user' => auth()->user()->activePayingUser(), // 付费用户判断
+            'Shadowrocket_install' => 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Shadowrocket.plist', // 客户端安装
+            'Quantumult_install' => 'itms-services://?action=download-manifest&url='.sysConfig('website_url').'/clients/Quantumult.plist', // 客户端安装
+            'subscribe_status' => $subscribe->status, // 订阅连接
+            'link' => $subscribe_link,
+            'subscribe_link' => 'sub://'.base64url_encode($subscribe_link),
+            'Shadowrocket_link' => 'shadowrocket://add/sub://'.base64url_encode($subscribe_link).'?remarks='.(sysConfig('website_name').'-'.sysConfig('website_url')),
+            'Shadowrocket_linkQrcode' => 'sub://'.base64url_encode($subscribe_link).'#'.base64url_encode(sysConfig('website_name')),
+            'Quantumult_linkOut' => 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Pro.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'),
+            'Quantumult_linkIn' => 'quantumult://configuration?server='.base64url_encode($subscribe_link).'&filter='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/BacktoCN.conf').'&rejection='.base64url_encode('https://raw.githubusercontent.com/ZBrettonYe/VPN-Rules-Collection/master/Profiles/Quantumult/Rejection.conf'),
+        ]);
     }
 
     // 更换订阅地址
@@ -561,10 +533,10 @@ class UserController extends Controller
             DB::beginTransaction();
 
             // 更换订阅码
-            Auth::getUser()->subscribe->update(['code' => Helpers::makeSubscribeCode()]);
+            auth()->user()->subscribe->update(['code' => Helpers::makeSubscribeCode()]);
 
             // 更换连接信息
-            Auth::getUser()->update(['passwd' => Str::random(), 'vmess_id' => Str::uuid()]);
+            auth()->user()->update(['passwd' => Str::random(), 'vmess_id' => Str::uuid()]);
 
             DB::commit();
 
@@ -586,7 +558,7 @@ class UserController extends Controller
         }
 
         // 管理员信息重新写入user
-        $user = Auth::loginUsingId(Session::get('admin'));
+        $user = auth()->loginUsingId(Session::get('admin'));
         Session::forget('admin');
         if ($user) {
             return Response::json(['status' => 'success', 'message' => '身份切换成功']);
@@ -615,14 +587,14 @@ class UserController extends Controller
         try {
             DB::beginTransaction();
             // 写入日志
-            $user = Auth::getUser();
+            $user = auth()->user();
             Helpers::addUserCreditLog($user->id, null, $user->credit, $user->credit + $coupon->value, $coupon->value, '用户手动充值 - [充值券:'.$request->input('coupon_sn').']');
 
             // 余额充值
             $user->updateCredit($coupon->value);
 
             // 更改卡券状态
-            Coupon::find($coupon->id)->update(['status' => 1]);
+            $coupon->update(['status' => 1]);
 
             // 写入卡券日志
             Helpers::addCouponLog('账户余额充值使用', $coupon->id);

+ 5 - 5
app/Http/Requests/Admin/ArticleRequest.php

@@ -9,12 +9,12 @@ class ArticleRequest extends FormRequest
     public function rules(): array
     {
         return [
-            'title' => 'required',
-            'type' => 'required|numeric',
-            'summary' => 'nullable',
-            'logo' => 'nullable|exclude_if:type,4|image',
-            'content' => 'required',
+            'type' => 'required|numeric|between:1,4',
+            'title' => 'required|string',
+            'summary' => 'string|nullable',
             'sort' => 'required_if:type,1|numeric',
+            'logo' => 'nullable|exclude_if:type,4|image',
+            'content' => 'required|string',
         ];
     }
 }

+ 17 - 0
app/Http/Requests/Admin/CertRequest.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CertRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'domain' => 'required|string',
+            'key' => 'string|nullable',
+            'pem' => 'string|nullable',
+        ];
+    }
+}

+ 5 - 4
app/Http/Requests/Admin/CouponRequest.php

@@ -9,13 +9,14 @@ class CouponRequest extends FormRequest
     public function rules(): array
     {
         return [
-            'name' => 'required',
+            'name' => 'required|string',
             'sn' => 'unique:coupon',
             'logo' => 'nullable|image',
-            'type' => 'required|integer|between:1,3',
-            'usable_times' => 'integer|nullable',
-            'num' => 'required|integer|min:1',
+            'type' => 'required|numeric|between:1,3',
+            'usable_times' => 'numeric|nullable',
             'value' => 'required|numeric|min:0',
+            'rule' => 'required_unless:type,3',
+            'num' => 'required|numeric|min:1',
             'start_time' => 'required|date|before_or_equal:end_time',
             'end_time' => 'required|date|after_or_equal:start_time',
         ];

+ 16 - 0
app/Http/Requests/Admin/PermissionRequest.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class PermissionRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'name' => 'required|string',
+            'description' => 'required|string',
+        ];
+    }
+}

+ 16 - 0
app/Http/Requests/Admin/RbacRequest.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class RbacRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'name' => 'required|string',
+            'description' => 'required|string',
+        ];
+    }
+}

+ 17 - 0
app/Http/Requests/Admin/RoleRequest.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class RoleRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'name' => 'required|string',
+            'description' => 'required|string',
+            'permissions' => 'exists:permissions,name',
+        ];
+    }
+}

+ 17 - 0
app/Http/Requests/Admin/RuleGroupRequest.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class RuleGroupRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'name' => 'required|string',
+            'type' => 'required|boolean',
+            'rules' => 'exists:rule,id',
+        ];
+    }
+}

+ 17 - 0
app/Http/Requests/Admin/RuleRequest.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class RuleRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'type' => 'required|numeric|between:1,4',
+            'name' => 'required|string',
+            'pattern' => 'required|string',
+        ];
+    }
+}

+ 16 - 0
app/Http/Requests/Admin/UserGroupRequest.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Http\Requests\Admin;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class UserGroupRequest extends FormRequest
+{
+    public function rules()
+    {
+        return [
+            'name' => 'required|string',
+            'nodes' => 'exists:node,id',
+        ];
+    }
+}

+ 12 - 1
app/Models/Coupon.php

@@ -13,12 +13,23 @@ class Coupon extends Model
     use SoftDeletes;
 
     protected $table = 'coupon';
+    protected $casts = ['start_time' => 'date:Y-m-d', 'end_time' => 'date:Y-m-d'];
     protected $dates = ['deleted_at'];
-    protected $fillable = ['usable_times', 'status'];
+    protected $guarded = [];
 
     // 筛选类型
     public function scopeType($query, $type)
     {
         return $query->whereType($type);
     }
+
+    public function setStartTimeAttribute($value)
+    {
+        return $this->attributes['start_time'] = strtotime($value);
+    }
+
+    public function setEndTimeAttribute($value)
+    {
+        return $this->attributes['end_time'] = strtotime($value);
+    }
 }

+ 2 - 2
app/Models/Label.php

@@ -14,8 +14,8 @@ class Label extends Model
     protected $table = 'label';
     protected $guarded = ['id'];
 
-    public function nodes(): HasMany
+    public function nodes()
     {
-        return $this->hasMany(NodeLabel::class);
+        return $this->belongsToMany(Node::class);
     }
 }

+ 13 - 20
app/Models/Node.php

@@ -3,6 +3,8 @@
 namespace App\Models;
 
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\Relations\HasOne;
 
@@ -11,12 +13,12 @@ use Illuminate\Database\Eloquent\Relations\HasOne;
  */
 class Node extends Model
 {
-    protected $table = 'ss_node';
-    protected $guarded = ['id', 'created_at'];
+    protected $table = 'node';
+    protected $guarded = [];
 
-    public function labels(): HasMany
+    public function labels()
     {
-        return $this->hasMany(NodeLabel::class);
+        return $this->belongsToMany(Label::class);
     }
 
     public function heartBeats(): HasMany
@@ -44,14 +46,14 @@ class Node extends Model
         return $this->hasMany(NodeHourlyDataFlow::class);
     }
 
-    public function rules(): hasMany
+    public function ruleGroup(): BelongsTo
     {
-        return $this->hasMany(NodeRule::class);
+        return $this->belongsTo(RuleGroup::class);
     }
 
-    public function ruleGroup(): hasOne
+    public function userGroups(): BelongsToMany
     {
-        return $this->hasOne(RuleGroupNode::class);
+        return $this->belongsToMany(UserGroup::class);
     }
 
     public function auth(): HasOne
@@ -64,14 +66,10 @@ class Node extends Model
         return $this->hasOne(Level::class, 'level', 'level');
     }
 
-    public function scopeUserAllowNodes($query, $user_group_id, $user_level)
+    public function users()
     {
-        $userGroup = UserGroup::find($user_group_id);
-        if ($userGroup) {
-            $query->whereIn('id', $userGroup->nodes);
-        }
-
-        return $query->whereStatus(1)->where('level', '<=', $user_level ?: 0);
+        return User::activeUser()->whereIn('user_group_id', $this->userGroups->pluck('id')->toArray())->orwhereNull('user_group_id')->where('level', '>=',
+            $this->attributes['level'])->get();
     }
 
     public function config($user)
@@ -149,11 +147,6 @@ class Node extends Model
         return $this->attributes['speed_limit'] = $value * Mbps;
     }
 
-    public function getNodeAccessUsersAttribute()
-    {
-        return User::nodeAllowUsers($this->attributes['id'], $this->attributes['level'])->get();
-    }
-
     public function getTypeLabelAttribute(): string
     {
         switch ($this->attributes['type']) {

+ 2 - 2
app/Models/NodeHeartBeat.php

@@ -7,10 +7,10 @@ use Illuminate\Database\Eloquent\Model;
 /**
  * 节点负载信息.
  */
-class NodeHeartBeat extends Model
+class NodeHeartbeat extends Model
 {
     public $timestamps = false;
-    protected $table = 'ss_node_info';
+    protected $table = 'node_heartbeat';
 
     public function scopeRecently($query)
     {

+ 0 - 25
app/Models/NodeLabel.php

@@ -1,25 +0,0 @@
-<?php
-
-namespace App\Models;
-
-use Illuminate\Database\Eloquent\Model;
-use Illuminate\Database\Eloquent\Relations\BelongsTo;
-
-/**
- * 节点标签.
- */
-class NodeLabel extends Model
-{
-    public $timestamps = false;
-    protected $table = 'node_label';
-
-    public function node(): BelongsTo
-    {
-        return $this->belongsTo(Node::class);
-    }
-
-    public function label(): BelongsTo
-    {
-        return $this->belongsTo(Label::class);
-    }
-}

+ 2 - 2
app/Models/NodeOnlineUserIp.php → app/Models/NodeOnlineIp.php

@@ -8,10 +8,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
 /**
  * 节点在线用户IP信息.
  */
-class NodeOnlineUserIp extends Model
+class NodeOnlineIp extends Model
 {
     public $timestamps = false;
-    protected $table = 'ss_node_ip';
+    protected $table = 'node_online_ip';
 
     public function node(): BelongsTo
     {

+ 1 - 1
app/Models/NodeOnlineLog.php

@@ -10,5 +10,5 @@ use Illuminate\Database\Eloquent\Model;
 class NodeOnlineLog extends Model
 {
     public $timestamps = false;
-    protected $table = 'ss_node_online_log';
+    protected $table = 'node_online_log';
 }

+ 0 - 13
app/Models/NodeRule.php

@@ -1,13 +0,0 @@
-<?php
-
-namespace App\Models;
-
-use Illuminate\Database\Eloquent\Model;
-
-/**
- * 节点审计规则关联.
- */
-class NodeRule extends Model
-{
-    protected $table = 'node_rule';
-}

+ 5 - 5
app/Models/Order.php

@@ -14,7 +14,7 @@ class Order extends Model
 {
     protected $table = 'order';
     protected $dates = ['expired_at'];
-    protected $fillable = ['expired_at', 'is_expire', 'status'];
+    protected $guarded = [];
 
     public function user(): BelongsTo
     {
@@ -58,15 +58,15 @@ class Order extends Model
 
     public function scopeActivePlan($query)
     {
-        return $query->active()->with('goods')->whereHas('goods', static function ($list) {
-            $list->whereType(2);
+        return $query->active()->with('goods')->whereHas('goods', static function ($query) {
+            $query->whereType(2);
         });
     }
 
     public function scopeActivePackage($query)
     {
-        return $query->active()->with('goods')->whereHas('goods', static function ($list) {
-            $list->whereType(1);
+        return $query->active()->with('goods')->whereHas('goods', static function ($query) {
+            $query->whereType(1);
         });
     }
 

+ 5 - 0
app/Models/ReferralApply.php

@@ -24,6 +24,11 @@ class ReferralApply extends Model
         return $this->belongsTo(User::class);
     }
 
+    public function referral_logs()
+    {
+        return ReferralLog::whereIn('id', $this->link_logs);
+    }
+
     public function getBeforeAttribute($value)
     {
         return $value / 100;

+ 5 - 0
app/Models/Rule.php

@@ -56,4 +56,9 @@ class Rule extends Model
 
         return $type_api_label;
     }
+
+    public function rule_groups()
+    {
+        return $this->belongsToMany(RuleGroup::class);
+    }
 }

+ 6 - 2
app/Models/RuleGroup.php

@@ -10,8 +10,7 @@ use Illuminate\Database\Eloquent\Model;
 class RuleGroup extends Model
 {
     protected $table = 'rule_group';
-    protected $casts = ['rules' => 'array', 'nodes' => 'array'];
-    protected $guarded = ['id'];
+    protected $guarded = [];
 
     public function getTypeLabelAttribute(): string
     {
@@ -23,4 +22,9 @@ class RuleGroup extends Model
 
         return $type_label;
     }
+
+    public function rules()
+    {
+        return $this->belongsToMany(Rule::class);
+    }
 }

+ 0 - 13
app/Models/RuleGroupNode.php

@@ -1,13 +0,0 @@
-<?php
-
-namespace App\Models;
-
-use Illuminate\Database\Eloquent\Model;
-
-/**
- * 审计规则分组节点关联.
- */
-class RuleGroupNode extends Model
-{
-    protected $table = 'rule_group_node';
-}

+ 7 - 1
app/Models/Ticket.php

@@ -5,6 +5,7 @@ namespace App\Models;
 use Auth;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\HasMany;
 
 /**
  * 工单.
@@ -25,7 +26,12 @@ class Ticket extends Model
 
     public function admin(): BelongsTo
     {
-        return $this->BelongsTo(User::class);
+        return $this->belongsTo(User::class);
+    }
+
+    public function reply(): HasMany
+    {
+        return $this->hasMany(TicketReply::class);
     }
 
     public function close(): bool

+ 10 - 19
app/Models/User.php

@@ -22,7 +22,7 @@ class User extends Authenticatable implements JWTSubject
     protected $table = 'user';
     protected $casts = ['expired_at' => 'date:Y-m-d', 'reset_time' => 'date:Y-m-d', 'ban_time' => 'date:Y-m-d'];
     protected $dates = ['expired_at', 'reset_time'];
-    protected $guarded = ['id'];
+    protected $guarded = [];
 
     public function usedTrafficPercentage()
     {
@@ -63,7 +63,7 @@ class User extends Authenticatable implements JWTSubject
 
     public function onlineIpLogs(): HasMany
     {
-        return $this->hasMany(NodeOnlineUserIp::class);
+        return $this->hasMany(NodeOnlineIp::class);
     }
 
     public function payments(): HasMany
@@ -151,11 +151,6 @@ class User extends Authenticatable implements JWTSubject
         return $this->hasMany(Verify::class);
     }
 
-    public function group(): BelongsTo
-    {
-        return $this->belongsTo(UserGroup::class);
-    }
-
     public function inviter(): BelongsTo
     {
         return $this->belongsTo(__CLASS__);
@@ -221,24 +216,20 @@ class User extends Authenticatable implements JWTSubject
         return $query->where('status', '<>', -1)->whereEnable(1);
     }
 
-    public function scopeNodeAllowUsers($query, $node_id, $node_level)
+    public function nodes()
     {
-        $groups = [0];
-        if ($node_id) {
-            foreach (UserGroup::all() as $userGroup) {
-                $nodes = $userGroup->nodes;
-                if ($nodes && in_array($node_id, $nodes)) {
-                    $groups[] = $userGroup->id;
-                }
-            }
+        if ($this->attributes['user_group_id']) {
+            $query = $this->group->nodes();
+        } else {
+            $query = Node::query();
         }
 
-        return $query->activeUser()->whereIn('group_id', $groups)->where('level', '>=', $node_level);
+        return $query->whereStatus(1)->where('level', '<=', $this->attributes['level'] ?? 0);
     }
 
-    public function scopeUserAccessNodes()
+    public function group(): BelongsTo
     {
-        return Node::userAllowNodes($this->attributes['group_id'] ?? 0, $this->attributes['level'] ?? 0);
+        return $this->belongsTo(UserGroup::class);
     }
 
     public function getIsAvailableAttribute(): bool

+ 11 - 2
app/Models/UserGroup.php

@@ -11,6 +11,15 @@ class UserGroup extends Model
 {
     public $timestamps = false;
     protected $table = 'user_group';
-    protected $casts = ['nodes' => 'array'];
-    protected $guarded = ['id'];
+    protected $guarded = [];
+
+    public function users()
+    {
+        return $this->hasMany(User::class);
+    }
+
+    public function nodes()
+    {
+        return $this->belongsToMany(Node::class);
+    }
 }

+ 1 - 1
app/Models/UserSubscribe.php

@@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
 class UserSubscribe extends Model
 {
     protected $table = 'user_subscribe';
-    protected $guarded = ['id', 'user_id'];
+    protected $guarded = [];
 
     public function scopeUid($query)
     {

+ 0 - 34
app/Observers/RuleGroupObserver.php

@@ -1,34 +0,0 @@
-<?php
-
-namespace App\Observers;
-
-use App\Jobs\VNet\reloadNode;
-use App\Models\Node;
-use App\Models\RuleGroup;
-use Arr;
-
-class RuleGroupObserver
-{
-    public function updated(RuleGroup $ruleGroup): void
-    {
-        $changes = $ruleGroup->getChanges();
-        if ($ruleGroup->nodes && Arr::hasAny($changes, ['type', 'rules'])) {
-            $nodes = Node::whereType(4)->whereIn('id', $ruleGroup->nodes)->get();
-            if ($nodes->isNotEmpty()) {
-                reloadNode::dispatch($nodes);
-            }
-        } elseif ($ruleGroup->rules && Arr::exists($changes, 'nodes')) {
-            $arrayDiff = array_merge(
-                array_diff($ruleGroup->nodes ?? [], $ruleGroup->getOriginal('nodes') ?? []),
-                array_diff($ruleGroup->getOriginal('nodes') ?? [], $ruleGroup->nodes ?? [])
-            );
-
-            if ($arrayDiff) {
-                $nodes = Node::whereType(4)->whereIn('id', $arrayDiff)->get();
-                if ($nodes->isNotEmpty()) {
-                    reloadNode::dispatch($nodes);
-                }
-            }
-        }
-    }
-}

+ 3 - 3
app/Observers/UserObserver.php

@@ -19,7 +19,7 @@ class UserObserver
         $subscribe->code = Helpers::makeSubscribeCode();
         $subscribe->save();
 
-        $allowNodes = $user->userAccessNodes()->whereType(4)->pluck('id');
+        $allowNodes = $user->nodes()->whereType(4)->pluck('id');
         if ($allowNodes) {
             addUser::dispatch($user->id, $allowNodes);
         }
@@ -28,7 +28,7 @@ class UserObserver
     public function updated(User $user): void
     {
         $changes = $user->getChanges();
-        $allowNodes = $user->userAccessNodes()->whereType(4)->get();
+        $allowNodes = $user->nodes()->whereType(4)->get();
         if ($allowNodes->isNotEmpty() && Arr::hasAny($changes, ['level', 'group_id', 'port', 'passwd', 'speed_limit', 'enable'])) {
             editUser::dispatch($user, $allowNodes);
         }
@@ -36,7 +36,7 @@ class UserObserver
 
     public function deleted(User $user): void
     {
-        $allowNodes = $user->userAccessNodes()->whereType(4)->get();
+        $allowNodes = $user->nodes()->whereType(4)->get();
         if ($allowNodes->isNotEmpty()) {
             delUser::dispatch($user->id, $allowNodes);
         }

+ 0 - 2
app/Providers/AppServiceProvider.php

@@ -5,7 +5,6 @@ namespace App\Providers;
 use App\Models\Config;
 use App\Models\Node;
 use App\Models\Order;
-use App\Models\RuleGroup;
 use App\Models\User;
 use App\Models\UserGroup;
 use App\Observers\ConfigObserver;
@@ -51,7 +50,6 @@ class AppServiceProvider extends ServiceProvider
         Config::observe(ConfigObserver::class);
         Node::observe(NodeObserver::class);
         Order::observe(OrderObserver::class);
-        RuleGroup::observe(RuleGroupObserver::class);
         UserGroup::observe(UserGroupObserver::class);
         User::observe(UserObserver::class);
     }

+ 0 - 17
app/Services/NodeService.php

@@ -4,7 +4,6 @@ namespace App\Services;
 
 use App\Components\IP;
 use App\Models\Node;
-use App\Models\NodeLabel;
 
 class NodeService
 {
@@ -26,20 +25,4 @@ class NodeService
 
         return $result;
     }
-
-    // 生成节点标签
-    public function makeLabels($nodeId, $labels): void
-    {
-        // 先删除所有该节点的标签
-        NodeLabel::whereNodeId($nodeId)->delete();
-
-        if (! empty($labels) && is_array($labels)) {
-            foreach ($labels as $label) {
-                $nodeLabel = new NodeLabel();
-                $nodeLabel->node_id = $nodeId;
-                $nodeLabel->label_id = $label;
-                $nodeLabel->save();
-            }
-        }
-    }
 }

File diff suppressed because it is too large
+ 274 - 150
composer.lock


+ 1 - 1
config/version.php

@@ -2,5 +2,5 @@
 
 return [
     'name' => 'ProxyPanel',
-    'number' => '2.5.x',
+    'number' => '2.6.a',
 ];

+ 8 - 1
database/factories/UserFactory.php

@@ -1,16 +1,23 @@
 <?php
 
-/** @var \Illuminate\Database\Eloquent\Factory $factory */
+/** @var Factory $factory */
 
 use App\Models\User;
 use Faker\Generator as Faker;
+use Illuminate\Database\Eloquent\Factory;
 
 $factory->define(User::class, function (Faker $faker) {
     return [
         'username' => $faker->name,
         'email' => $faker->unique()->safeEmail,
         'password' => Hash::make(Str::random()),
+        'port' => Helpers::getPort(),
         'passwd' => Str::random(),
         'vmess_id' => $faker->uuid,
+        'method' => Helpers::getDefaultMethod(),
+        'protocol' => Helpers::getDefaultProtocol(),
+        'obfs' => Helpers::getDefaultObfs(),
+        'transfer_enable' => (int) sysConfig('default_traffic') * MB,
+        'expired_at' => date('Y-m-d', strtotime('+'.sysConfig('default_days').' days')),
     ];
 });

+ 192 - 0
database/migrations/2020_12_24_074739_table_improvement.php

@@ -0,0 +1,192 @@
+<?php
+
+use App\Models\Coupon;
+use App\Models\Node;
+use App\Models\NodeOnlineIp;
+use App\Models\Order;
+use App\Models\RuleGroup;
+use App\Models\User;
+use App\Models\UserGroup;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class TableImprovement extends Migration
+{
+    public function up()
+    {
+        // ----- 开始 数据库表关系优化 -----
+        Schema::table('level', function (Blueprint $table) {
+            $table->unique('level');
+        });
+
+        Schema::table('node_certificate', function (Blueprint $table) {
+            $table->unique('domain');
+        });
+
+        Schema::table('ss_node', function (Blueprint $table) {
+            $table->unsignedInteger('rule_group_id')->nullable()->comment('从属规则分组ID')->after('level');
+            $table->foreign('rule_group_id')->references('id')->on('rule_group')->nullOnDelete();
+            $table->rename('node');
+        });
+
+        Schema::table('ss_node_info', function (Blueprint $table) {
+            $table->unsignedInteger('node_id')->comment('节点ID')->change();
+            $table->rename('node_heartbeat');
+        });
+
+        Schema::table('ss_node_ip', function (Blueprint $table) {
+            $table->rename('node_online_ip');
+        });
+        NodeOnlineIp::whereNodeId(0)->update(['node_id' => null]);
+        NodeOnlineIp::whereUserId(0)->update(['user_id' => null]);
+        Schema::table('node_online_ip', function (Blueprint $table) {
+            $table->unsignedInteger('node_id')->comment('节点ID')->change();
+            $table->unsignedInteger('user_id')->default(null)->nullable()->change();
+        });
+
+        Schema::table('ss_node_online_log', function (Blueprint $table) {
+            $table->rename('node_online_log');
+        });
+
+        Schema::table('node_label', function (Blueprint $table) {
+            $table->unsignedInteger('node_id')->comment('节点ID')->change();
+            $table->unsignedInteger('label_id')->comment('标签ID')->change();
+            $table->unique(['node_id', 'label_id']);
+            $table->rename('label_node');
+        });
+
+        Schema::table('node_ping', function (Blueprint $table) {
+            $table->unsignedInteger('node_id')->comment('对应节点ID')->change();
+        });
+
+        Order::whereGoodsId(0)->update(['goods_id' => null]);
+        Order::whereCouponId(0)->orWhereNotIn('coupon_id', Coupon::withTrashed()->pluck('id')->toArray())->update(['coupon_id' => null]);
+        Schema::table('order', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('购买者ID')->change();
+            $table->foreign('goods_id')->references('id')->on('goods')->nullOnDelete();
+            $table->foreign('coupon_id')->references('id')->on('coupon')->nullOnDelete();
+        });
+
+        Schema::create('node_user_group', function (Blueprint $table) {
+            $table->increments('id');
+            $table->unsignedInteger('node_id')->comment('节点ID');
+            $table->unsignedInteger('user_group_id')->comment('从属用户分组ID');
+
+            $table->unique(['user_group_id', 'node_id']);
+            $table->foreign('node_id')->references('id')->on('node')->cascadeOnDelete();
+            $table->foreign('user_group_id')->references('id')->on('user_group')->cascadeOnDelete();
+        });
+
+        Schema::table('payment', function (Blueprint $table) {
+            $table->foreign('order_id')->references('id')->on('order')->cascadeOnDelete();
+        });
+
+        Schema::table('referral_apply', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('申请者ID')->change();
+        });
+
+        Schema::table('rule_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('触发者ID')->change();
+        });
+
+        Schema::create('rule_rule_group', function (Blueprint $table) {
+            $table->increments('id');
+            $table->unsignedInteger('rule_id')->comment('规则ID');
+            $table->unsignedInteger('rule_group_id')->comment('从属规则分组ID');
+
+            $table->unique(['rule_group_id', 'rule_id']);
+            $table->foreign('rule_id')->references('id')->on('rule')->cascadeOnDelete();
+            $table->foreign('rule_group_id')->references('id')->on('rule_group')->cascadeOnDelete();
+        });
+
+        Schema::table('ticket', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('ticket_reply', function (Blueprint $table) {
+            $table->unsignedInteger('ticket_id')->comment('工单ID')->change();
+        });
+
+        Schema::table('user', function (Blueprint $table) {
+            $table->unsignedInteger('group_id')->nullable()->default(null)->comment('所属分组')->change();
+        });
+        User::whereGroupId(0)->update(['group_id' => null]);
+        Schema::table('user', function (Blueprint $table) {
+            $table->renameColumn('group_id', 'user_group_id');
+            $table->foreign('user_group_id')->references('id')->on('user_group')->nullOnDelete();
+        });
+
+        Schema::table('user_baned_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_credit_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_daily_data_flow', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_data_modify_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_hourly_data_flow', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_login_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_subscribe', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+        });
+
+        Schema::table('user_traffic_log', function (Blueprint $table) {
+            $table->unsignedInteger('user_id')->comment('用户ID')->change();
+            $table->unsignedInteger('node_id')->comment('节点ID')->change();
+        });
+        // ----- 结束 数据库表关系优化 -----
+
+        // ----- 开始 数据转化 & 弃用数据 -----
+        foreach (RuleGroup::all() as $group) {
+            $group->rules()->attach(json_decode($group->rules, true));
+            foreach (json_decode($group->nodes, true) as $id) {
+                $node = Node::find($id);
+                if ($node) {
+                    $node->update(['rule_group_id' => $group->id]);
+                }
+            }
+        }
+
+        foreach (UserGroup::all() as $group) {
+            $group->nodes()->attach(json_decode($group->nodes, true));
+        }
+
+        Schema::table('rule_group', function (Blueprint $table) {
+            $table->dropColumn('nodes');
+            $table->dropColumn('rules');
+        });
+
+        Schema::table('user_group', function (Blueprint $table) {
+            $table->dropColumn('nodes');
+        });
+
+        Schema::table('node_rule', function (Blueprint $table) {
+            $table->drop();
+        });
+
+        Schema::table('rule_group_node', function (Blueprint $table) {
+            $table->drop();
+        });
+        // ----- 结束 数据转化 & 弃用数据 -----
+    }
+
+    public function down()
+    {
+        // 不可逆
+    }
+}

+ 4 - 1
database/seeds/DatabaseSeeder.php

@@ -1,5 +1,6 @@
 <?php
 
+use App\Models\User;
 use Illuminate\Database\Seeder;
 
 class DatabaseSeeder extends Seeder
@@ -11,6 +12,8 @@ class DatabaseSeeder extends Seeder
      */
     public function run()
     {
-        // $this->call(UserSeeder::class);
+        if (User::doesntExist()) {
+            $this->call(PresetSeeder::class);
+        }
     }
 }

+ 106 - 123
database/migrations/2020_08_21_150711_preset_data.php → database/seeds/PresetSeeder.php

@@ -8,73 +8,18 @@ use App\Models\Level;
 use App\Models\Rule;
 use App\Models\SsConfig;
 use App\Models\User;
-use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Seeder;
 
-class PresetData extends Migration
+class PresetSeeder extends Seeder
 {
     /**
-     * Run the migrations.
+     * Run the database seeds.
      *
      * @return void
      */
-    public function up()
+    public function run()
     {
-        // 生成初始管理账号
-        User::create([
-            'username' => '管理员',
-            'email'    => 'test@test.com',
-            'password' => '123456',
-            'port'     => 10000,
-            'passwd'   => Str::random(),
-            'vmess_id' => Str::uuid(),
-            'is_admin' => 1,
-        ]);
-
-        // 生成最初的等级
-        Level::insert(['level' => 0, 'name' => 'Free']);
-        for ($i = 1; $i < 8; $i++) {
-            Level::insert(['level' => $i, 'name' => 'VIP-'.$i]);
-        }
-
-        // ss系列 加密方式
-        SsConfig::insert(['name' => 'none', 'type' => 1, 'is_default' => 1]);
-        SsConfig::insert(['name' => 'rc4-md5']);
-        SsConfig::insert(['name' => 'aes-128-cfb']);
-        SsConfig::insert(['name' => 'aes-192-cfb']);
-        SsConfig::insert(['name' => 'aes-256-cfb']);
-        SsConfig::insert(['name' => 'aes-128-ctr']);
-        SsConfig::insert(['name' => 'aes-192-ctr']);
-        SsConfig::insert(['name' => 'aes-256-ctr']);
-        SsConfig::insert(['name' => 'aes-128-gcm']);
-        SsConfig::insert(['name' => 'aes-192-gcm']);
-        SsConfig::insert(['name' => 'aes-256-gcm']);
-        SsConfig::insert(['name' => 'bf-cfb']);
-        SsConfig::insert(['name' => 'cast5-cfb']);
-        SsConfig::insert(['name' => 'des-cfb']);
-        SsConfig::insert(['name' => 'salsa20']);
-        SsConfig::insert(['name' => 'chacha20']);
-        SsConfig::insert(['name' => 'chacha20-ietf']);
-        SsConfig::insert(['name' => 'chacha20-ietf-poly1305']);
-
-        // ss系列 协议
-        SsConfig::insert(['name' => 'origin', 'type' => 2, 'is_default' => 1]);
-        SsConfig::insert(['name' => 'auth_sha1_v4', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_aes128_md5', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_aes128_sha1', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_a', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_b', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_c', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_d', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_e', 'type' => 2]);
-        SsConfig::insert(['name' => 'auth_chain_f', 'type' => 2]);
-
-        // ss系列 混淆
-        SsConfig::insert(['name' => 'plain', 'type' => 3, 'is_default' => 1]);
-        SsConfig::insert(['name' => 'http_simple', 'type' => 3]);
-        SsConfig::insert(['name' => 'http_post', 'type' => 3]);
-        SsConfig::insert(['name' => 'tls1.2_ticket_auth', 'type' => 3]);
-        SsConfig::insert(['name' => 'tls1.2_ticket_fastauth', 'type' => 3]);
-
+        // 系统参数
         $configList = [
             'is_rand_port',
             'is_user_rand_port',
@@ -198,49 +143,94 @@ class PresetData extends Migration
         }
 
         $presetDates = [
-            'invite_num'              => 3,
-            'is_register'             => 1,
-            'is_invite_register'      => 2,
-            'website_name'            => 'ProxyPanel',
-            'is_reset_password'       => 1,
-            'reset_password_times'    => 3,
-            'website_url'             => 'https://demo.proxypanel.ml',
-            'active_times'            => 3,
-            'is_checkin'              => 1,
-            'min_rand_traffic'        => 10,
-            'max_rand_traffic'        => 500,
-            'traffic_limit_time'      => 1440,
-            'referral_traffic'        => 1024,
-            'referral_percent'        => 0.2,
-            'referral_money'          => 100,
-            'referral_status'         => 1,
-            'default_traffic'         => 1024,
+            'invite_num' => 3,
+            'is_register' => 1,
+            'is_invite_register' => 2,
+            'website_name' => 'ProxyPanel',
+            'is_reset_password' => 1,
+            'reset_password_times' => 3,
+            'website_url' => 'https://demo.proxypanel.ml',
+            'active_times' => 3,
+            'is_checkin' => 1,
+            'min_rand_traffic' => 10,
+            'max_rand_traffic' => 500,
+            'traffic_limit_time' => 1440,
+            'referral_traffic' => 1024,
+            'referral_percent' => 0.2,
+            'referral_money' => 100,
+            'referral_status' => 1,
+            'default_traffic' => 1024,
             'traffic_warning_percent' => 80,
-            'expire_days'             => 15,
-            'reset_traffic'           => 1,
-            'default_days'            => 7,
-            'subscribe_max'           => 3,
-            'min_port'                => 10000,
-            'max_port'                => 65535,
-            'is_traffic_ban'          => 1,
-            'traffic_ban_value'       => 10,
-            'traffic_ban_time'        => 60,
-            'is_clear_log'            => 1,
-            'is_subscribe_ban'        => 1,
-            'subscribe_ban_times'     => 20,
-            'auto_release_port'       => 1,
-            'register_ip_limit'       => 5,
-            'detection_check_times'   => 3,
-            'alipay_transport'        => 'http',
-            'alipay_currency'         => 'USD',
-            'user_invite_days'        => 7,
-            'admin_invite_days'       => 7,
+            'expire_days' => 15,
+            'reset_traffic' => 1,
+            'default_days' => 7,
+            'subscribe_max' => 3,
+            'min_port' => 10000,
+            'max_port' => 65535,
+            'is_traffic_ban' => 1,
+            'traffic_ban_value' => 10,
+            'traffic_ban_time' => 60,
+            'is_clear_log' => 1,
+            'is_subscribe_ban' => 1,
+            'subscribe_ban_times' => 20,
+            'auto_release_port' => 1,
+            'register_ip_limit' => 5,
+            'detection_check_times' => 3,
+            'alipay_transport' => 'http',
+            'alipay_currency' => 'USD',
+            'user_invite_days' => 7,
+            'admin_invite_days' => 7,
         ];
 
         foreach ($presetDates as $key => $value) {
             Config::find($key)->update(['value' => $value]);
         }
 
+        // 生成最初的等级
+        Level::insert(['level' => 0, 'name' => 'Free']);
+        for ($i = 1; $i < 8; $i++) {
+            Level::insert(['level' => $i, 'name' => 'VIP-'.$i]);
+        }
+
+        // ss系列 加密方式
+        SsConfig::insert(['name' => 'none', 'type' => 1, 'is_default' => 1]);
+        SsConfig::insert(['name' => 'rc4-md5']);
+        SsConfig::insert(['name' => 'aes-128-cfb']);
+        SsConfig::insert(['name' => 'aes-192-cfb']);
+        SsConfig::insert(['name' => 'aes-256-cfb']);
+        SsConfig::insert(['name' => 'aes-128-ctr']);
+        SsConfig::insert(['name' => 'aes-192-ctr']);
+        SsConfig::insert(['name' => 'aes-256-ctr']);
+        SsConfig::insert(['name' => 'aes-128-gcm']);
+        SsConfig::insert(['name' => 'aes-192-gcm']);
+        SsConfig::insert(['name' => 'aes-256-gcm']);
+        SsConfig::insert(['name' => 'bf-cfb']);
+        SsConfig::insert(['name' => 'cast5-cfb']);
+        SsConfig::insert(['name' => 'des-cfb']);
+        SsConfig::insert(['name' => 'salsa20']);
+        SsConfig::insert(['name' => 'chacha20']);
+        SsConfig::insert(['name' => 'chacha20-ietf']);
+        SsConfig::insert(['name' => 'chacha20-ietf-poly1305']);
+
+        // ss系列 协议
+        SsConfig::insert(['name' => 'origin', 'type' => 2, 'is_default' => 1]);
+        SsConfig::insert(['name' => 'auth_sha1_v4', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_aes128_md5', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_aes128_sha1', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_a', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_b', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_c', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_d', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_e', 'type' => 2]);
+        SsConfig::insert(['name' => 'auth_chain_f', 'type' => 2]);
+
+        // ss系列 混淆
+        SsConfig::insert(['name' => 'plain', 'type' => 3, 'is_default' => 1]);
+        SsConfig::insert(['name' => 'http_simple', 'type' => 3]);
+        SsConfig::insert(['name' => 'http_post', 'type' => 3]);
+        SsConfig::insert(['name' => 'tls1.2_ticket_auth', 'type' => 3]);
+        SsConfig::insert(['name' => 'tls1.2_ticket_fastauth', 'type' => 3]);
+
         // 节点用标签
         $labelList = [
             'Netflix',
@@ -499,39 +489,32 @@ class PresetData extends Migration
 
         // 审核规则
         $ruleList = [
-            '360'     => '(.*.||)(^360|0360|1360|3600|360safe|^so|qhimg|qhmsg|^yunpan|qihoo|qhcdn|qhupdate|360totalsecurity|360shouji|qihucdn|360kan|secmp).(cn|com|net)',
-            '腾讯管家'    => '(.guanjia.qq.com|qqpcmgr|QQPCMGR)',
-            '金山毒霸'    => '(.*.||)(rising|kingsoft|duba|xindubawukong|jinshanduba).(com|net|org)',
-            '暗网相关'    => '(.*.||)(netvigator|torproject).(cn|com|net|org)',
-            '百度定位'    => '(api|ps|sv|offnavi|newvector|ulog.imap|newloc|tracknavi)(.map|).(baidu|n.shifen).com',
-            '法轮功类'    => '(.*.||)(dafahao|minghui|dongtaiwang|dajiyuan|falundata|shenyun|tuidang|epochweekly|epochtimes|ntdtv|falundafa|wujieliulan|zhengjian).(org|com|net)',
-            'BT扩展名'   => '(torrent|.torrent|peer_id=|info_hash|get_peers|find_node|BitTorrent|announce_peer|announce.php?passkey=)',
-            '邮件滥发'    => '((^.*@)(guerrillamail|guerrillamailblock|sharklasers|grr|pokemail|spam4|bccto|chacuo|027168).(info|biz|com|de|net|org|me|la)|Subject|HELO|SMTP)',
-            '迅雷下载'    => '(.?)(xunlei|sandai|Thunder|XLLiveUD)(.)',
-            '大陆应用'    => '(.*.||)(baidu|qq|163|189|10000|10010|10086|sohu|sogoucdn|sogou|uc|58|taobao|qpic|bilibili|hdslb|acgvideo|sina|douban|doubanio|xiaohongshu|sinaimg|weibo|xiaomi|youzanyun|meituan|dianping|biliapi|huawei|pinduoduo|cnzz).(org|com|net|cn)',
-            '大陆银行'    => '(.*.||)(icbc|ccb|boc|bankcomm|abchina|cmbchina|psbc|cebbank|cmbc|pingan|spdb|citicbank|cib|hxb|bankofbeijing|hsbank|tccb|4001961200|bosc|hkbchina|njcb|nbcb|lj-bank|bjrcb|jsbchina|gzcb|cqcbank|czbank|hzbank|srcb|cbhb|cqrcb|grcbank|qdccb|bocd|hrbcb|jlbank|bankofdl|qlbchina|dongguanbank|cscb|hebbank|drcbank|zzbank|bsb|xmccb|hljrcc|jxnxs|gsrcu|fjnx|sxnxs|gx966888|gx966888|zj96596|hnnxs|ahrcu|shanxinj|hainanbank|scrcu|gdrcu|hbxh|ynrcc|lnrcc|nmgnxs|hebnx|jlnls|js96008|hnnx|sdnxs).(org|com|net|cn)',
-            '台湾银行'    => '(.*.||)(firstbank|bot|cotabank|megabank|tcb-bank|landbank|hncb|bankchb|tbb|ktb|tcbbank|scsb|bop|sunnybank|kgibank|fubon|ctbcbank|cathaybk|eximbank|bok|ubot|feib|yuantabank|sinopac|esunbank|taishinbank|jihsunbank|entiebank|hwataibank|csc|skbank).(org|com|net|tw)',
+            '360' => '(.*.||)(^360|0360|1360|3600|360safe|^so|qhimg|qhmsg|^yunpan|qihoo|qhcdn|qhupdate|360totalsecurity|360shouji|qihucdn|360kan|secmp).(cn|com|net)',
+            '腾讯管家' => '(.guanjia.qq.com|qqpcmgr|QQPCMGR)',
+            '金山毒霸' => '(.*.||)(rising|kingsoft|duba|xindubawukong|jinshanduba).(com|net|org)',
+            '暗网相关' => '(.*.||)(netvigator|torproject).(cn|com|net|org)',
+            '百度定位' => '(api|ps|sv|offnavi|newvector|ulog.imap|newloc|tracknavi)(.map|).(baidu|n.shifen).com',
+            '法轮功类' => '(.*.||)(dafahao|minghui|dongtaiwang|dajiyuan|falundata|shenyun|tuidang|epochweekly|epochtimes|ntdtv|falundafa|wujieliulan|zhengjian).(org|com|net)',
+            'BT扩展名' => '(torrent|.torrent|peer_id=|info_hash|get_peers|find_node|BitTorrent|announce_peer|announce.php?passkey=)',
+            '邮件滥发' => '((^.*@)(guerrillamail|guerrillamailblock|sharklasers|grr|pokemail|spam4|bccto|chacuo|027168).(info|biz|com|de|net|org|me|la)|Subject|HELO|SMTP)',
+            '迅雷下载' => '(.?)(xunlei|sandai|Thunder|XLLiveUD)(.)',
+            '大陆应用' => '(.*.||)(baidu|qq|163|189|10000|10010|10086|sohu|sogoucdn|sogou|uc|58|taobao|qpic|bilibili|hdslb|acgvideo|sina|douban|doubanio|xiaohongshu|sinaimg|weibo|xiaomi|youzanyun|meituan|dianping|biliapi|huawei|pinduoduo|cnzz).(org|com|net|cn)',
+            '大陆银行' => '(.*.||)(icbc|ccb|boc|bankcomm|abchina|cmbchina|psbc|cebbank|cmbc|pingan|spdb|citicbank|cib|hxb|bankofbeijing|hsbank|tccb|4001961200|bosc|hkbchina|njcb|nbcb|lj-bank|bjrcb|jsbchina|gzcb|cqcbank|czbank|hzbank|srcb|cbhb|cqrcb|grcbank|qdccb|bocd|hrbcb|jlbank|bankofdl|qlbchina|dongguanbank|cscb|hebbank|drcbank|zzbank|bsb|xmccb|hljrcc|jxnxs|gsrcu|fjnx|sxnxs|gx966888|gx966888|zj96596|hnnxs|ahrcu|shanxinj|hainanbank|scrcu|gdrcu|hbxh|ynrcc|lnrcc|nmgnxs|hebnx|jlnls|js96008|hnnx|sdnxs).(org|com|net|cn)',
+            '台湾银行' => '(.*.||)(firstbank|bot|cotabank|megabank|tcb-bank|landbank|hncb|bankchb|tbb|ktb|tcbbank|scsb|bop|sunnybank|kgibank|fubon|ctbcbank|cathaybk|eximbank|bok|ubot|feib|yuantabank|sinopac|esunbank|taishinbank|jihsunbank|entiebank|hwataibank|csc|skbank).(org|com|net|tw)',
             '大陆第三方支付' => '(.*.||)(alipay|baifubao|yeepay|99bill|95516|51credit|cmpay|tenpay|lakala|jdpay).(org|com|net|cn)',
-            '台湾特供'    => '(.*.||)(visa|mycard|mastercard|gov|gash|beanfun|bank|line).(org|com|net|cn|tw|jp|kr)',
-            '涉政治类'    => '(.*.||)(shenzhoufilm|secretchina|renminbao|aboluowang|mhradio|guangming|zhengwunet|soundofhope|yuanming|zhuichaguoji|fgmtv|xinsheng|shenyunperformingarts|epochweekly|tuidang|shenyun|falundata|bannedbook|pincong|rfi|mingjingnews|boxun|rfa|scmp|ogate|voachinese).(org|com|net|rocks|fr)',
-            '流媒体'     => '(.*.||)(youtube|googlevideo|hulu|netflix|nflxvideo|akamai|nflximg|hbo|mtv|bbc|tvb).(org|club|com|net|tv)',
-            '测速类'     => '(.*.||)(fast|speedtest).(org|com|net|cn)',
-            '外汇交易类'   => '(.*.||)(metatrader4|metatrader5|mql5).(org|com|net)',
+            '台湾特供' => '(.*.||)(visa|mycard|mastercard|gov|gash|beanfun|bank|line).(org|com|net|cn|tw|jp|kr)',
+            '涉政治类' => '(.*.||)(shenzhoufilm|secretchina|renminbao|aboluowang|mhradio|guangming|zhengwunet|soundofhope|yuanming|zhuichaguoji|fgmtv|xinsheng|shenyunperformingarts|epochweekly|tuidang|shenyun|falundata|bannedbook|pincong|rfi|mingjingnews|boxun|rfa|scmp|ogate|voachinese).(org|com|net|rocks|fr)',
+            '流媒体' => '(.*.||)(youtube|googlevideo|hulu|netflix|nflxvideo|akamai|nflximg|hbo|mtv|bbc|tvb).(org|club|com|net|tv)',
+            '测速类' => '(.*.||)(fast|speedtest).(org|com|net|cn)',
+            '外汇交易类' => '(.*.||)(metatrader4|metatrader5|mql5).(org|com|net)',
         ];
 
         foreach ($ruleList as $name => $pattern) {
             Rule::insert(['type' => 1, 'name' => $name, 'pattern' => $pattern]);
         }
-    }
 
-    /**
-     * Reverse the migrations.
-     *
-     * @return void
-     */
-    public function down()
-    {
-        echo 'plz run php artisan migrate:fresh'.PHP_EOL;
-        echo '请运行 php artisan migrate:fresh'.PHP_EOL;
+        // 生成初始管理账号
+        $user = factory(User::class)->create(['username' => '管理员', 'email' => 'test@test.com', 'password' => '123456']);
+        $user->assignRole('Super Admin');
     }
 }

+ 0 - 0
public/downloads/convert.json


+ 3 - 3
resources/views/admin/aff/detail.blade.php

@@ -8,9 +8,9 @@
             <div class="panel-heading">
                 <h2 class="panel-title">提现申请详情</h2>
                 <div class="panel-actions">
-                    @if($basic->status === -1)
+                    @if($referral->status === -1)
                         <span class="badge badge-lg badge-danger"> 已驳回 </span>
-                    @elseif($basic->status === 2)
+                    @elseif($referral->status === 2)
                         <span class="badge badge-lg badge-success"> 已打款 </span>
                     @endif
                     <a href="{{route('admin.aff.index')}}" class="btn btn-danger"> 返 回</a>
@@ -22,7 +22,7 @@
                         <thead class="thead-default">
                         <tr>
                             <th colspan="6">
-                                申请单ID:{{$basic->id}} | 申请人:{{$basic->user->email}} | 申请提现金额:¥{{$basic->amount}} | 申请时间:{{$basic->created_at}}
+                                申请单ID:{{$referral->id}} | 申请人:{{$referral->user->email}} | 申请提现金额:¥{{$referral->amount}} | 申请时间:{{$referral->created_at}}
                             </th>
                         </tr>
                         <tr>

+ 25 - 6
resources/views/admin/aff/index.blade.php

@@ -136,12 +136,31 @@
       @can('admin.aff.setStatus')
       // 更改状态
       function setStatus(id, status) {
-        $.post('{{route('admin.aff.setStatus')}}', {_token: '{{csrf_token()}}', id: id, status: status}, function(ret) {
-          if (ret.status === 'success') {
-            swal.fire({title: ret.message, icon: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.reload());
-          } else {
-            swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload());
-          }
+        $.ajax({
+          method: 'PUT',
+          url: '{{route('admin.aff.setStatus','')}}/' + id,
+          data: {
+            _token: '{{csrf_token()}}',
+            status: status,
+          },
+          dataType: 'json',
+          success: function(ret) {
+            if (ret.status === 'success') {
+              swal.fire({title: ret.message, icon: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.reload());
+            } else {
+              swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload());
+            }
+          },
+          error: function(data) {
+            let str = '';
+            const errors = data.responseJSON;
+            if ($.isEmptyObject(errors) === false) {
+              $.each(errors.errors, function(index, value) {
+                str += '<li>' + value + '</li>';
+              });
+              swal.fire({title: '提示', html: str, icon: 'error', confirmButtonText: '{{trans('home.ticket_confirm')}}'});
+            }
+          },
         });
       }
         @endcan

+ 15 - 15
resources/views/admin/aff/rebate.blade.php

@@ -44,32 +44,32 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($referralLogs as $referralLog)
                         <tr>
-                            <td> {{$vo->id}} </td>
+                            <td> {{$referralLog->id}} </td>
                             <td>
-                                @if(empty($vo->invitee))
+                                @if(empty($referralLog->invitee))
                                     【账号已删除】
                                 @else
-                                    <a href="{{route('admin.aff.rebate',['invitee_email' => $vo->invitee->email])}}"> {{$vo->invitee->email}} </a>
+                                    <a href="{{route('admin.aff.rebate',['invitee_email' => $referralLog->invitee->email])}}"> {{$referralLog->invitee->email}} </a>
                                 @endif
                             </td>
                             <td>
-                                @if(empty($vo->inviter))
+                                @if(empty($referralLog->inviter))
                                     【账号已删除】
                                 @else
-                                    <a href="{{route('admin.aff.rebate',['inviter_email' => $vo->inviter->email])}}"> {{$vo->inviter->email}} </a>
+                                    <a href="{{route('admin.aff.rebate',['inviter_email' => $referralLog->inviter->email])}}"> {{$referralLog->inviter->email}} </a>
                                 @endif
                             </td>
-                            <td> {{$vo->order_id}} </td>
-                            <td> {{$vo->amount}} </td>
-                            <td> {{$vo->commission}} </td>
-                            <td> {{$vo->created_at}} </td>
-                            <td> {{$vo->updated_at}} </td>
+                            <td> {{$referralLog->order_id}} </td>
+                            <td> {{$referralLog->amount}} </td>
+                            <td> {{$referralLog->commission}} </td>
+                            <td> {{$referralLog->created_at}} </td>
+                            <td> {{$referralLog->updated_at}} </td>
                             <td>
-                                @if ($vo->status === 1)
+                                @if ($referralLog->status === 1)
                                     <span class="badge badge-danger">申请中</span>
-                                @elseif($vo->status === 2)
+                                @elseif($referralLog->status === 2)
                                     <span class="badge badge-default">已提现</span>
                                 @else
                                     <span class="badge badge-info">未提现</span>
@@ -83,11 +83,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 个申请
+                        共 <code>{{$referralLogs->total()}}</code> 个申请
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$referralLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 1 - 1
resources/views/admin/article/edit.blade.php

@@ -16,7 +16,7 @@
                 <x-alert type="success" :message="Session::get('successMsg')"/>
             @endif
             <div class="panel-body">
-                <form action="{{route('admin.article.update', $article->id)}}" method="POST" enctype="multipart/form-data" class="form-horizontal">@method('PUT')@csrf
+                <form action="{{route('admin.article.update', $article)}}" method="POST" enctype="multipart/form-data" class="form-horizontal">@method('PUT')@csrf
                     <div class="form-group row">
                         <label for="type" class="col-form-label col-md-2">类型</label>
                         <div class="col-md-10 d-flex align-items-center">

+ 1 - 1
resources/views/admin/article/index.blade.php

@@ -42,7 +42,7 @@
                             @endif
                             <td>
                                 @can('admin.article.show')
-                                    <a href="{{route('admin.article.show',$article->id)}}" target="_blank"> {{Str::limit($article->title, 80)}} </a>
+                                    <a href="{{route('admin.article.show',$article)}}" target="_blank"> {{Str::limit($article->title, 80)}} </a>
                                 @else
                                     {{Str::limit($article->title, 80)}}
                                 @endcan

+ 5 - 5
resources/views/admin/config/config.blade.php

@@ -44,7 +44,7 @@
                                 </tr>
                                 </thead>
                                 <tbody>
-                                @foreach($methodList as $method)
+                                @foreach($methods as $method)
                                     <tr>
                                         <td> {{$method->name}}</td>
                                         <td>
@@ -78,7 +78,7 @@
                                 </tr>
                                 </thead>
                                 <tbody>
-                                @foreach($protocolList as $protocol)
+                                @foreach($protocols as $protocol)
                                     <tr>
                                         <td> {{$protocol->name}}</td>
                                         <td>
@@ -147,7 +147,7 @@
                                 </tr>
                                 </thead>
                                 <tbody>
-                                @foreach($levelList as $level)
+                                @foreach($levels as $level)
                                     <tr>
                                         <td>
                                             <input type="text" class="form-control" name="level" id="level_{{$level->id}}" value="{{$level->level}}"/>
@@ -182,7 +182,7 @@
                                 </tr>
                                 </thead>
                                 <tbody>
-                                @foreach($countryList as $country)
+                                @foreach($countries as $country)
                                     <tr>
                                         <td>
                                             <svg class="w-40 h-40 text-center" aria-hidden="true">
@@ -222,7 +222,7 @@
                                 </tr>
                                 </thead>
                                 <tbody>
-                                @foreach($labelList as $label)
+                                @foreach($labels as $label)
                                     <tr>
                                         <td>
                                             <input type="text" class="form-control" name="label_name" id="label_name_{{$label->id}}" value="{{$label->name}}"/>

+ 31 - 24
resources/views/admin/coupon/create.blade.php

@@ -96,13 +96,14 @@
                                 <span class="input-group-text"><i class="icon wb-calendar" aria-hidden="true"></i></span>
                             </div>
                             <label for="start_time"></label>
-                            <input type="text" class="form-control" name="start_time" id="start_time" value="{{Request::old('start_time') ?? date("Y-m-d")}}" required/>
+                            <input type="text" class="form-control" name="start_time" id="start_time"
+                                   value="{{Request::old('start_time') ?? date("Y-m-d")}}" required/>
                             <div class="input-group-prepend">
                                 <span class="input-group-text">至</span>
                             </div>
                             <label for="end_time"></label>
-                            <input type="text" class="form-control" name="end_time" id="end_time" value="{{Request::old('end_time') ?? date("Y-m-d",strtotime("+1 month"))}}"
-                                   required/>
+                            <input type="text" class="form-control" name="end_time" id="end_time"
+                                   value="{{Request::old('end_time') ?? date("Y-m-d",strtotime("+1 month"))}}" required/>
                         </div>
                     </div>
                     <div class="form-actions col-12 text-right">
@@ -119,27 +120,33 @@
     <script src="/assets/global/js/Plugin/bootstrap-datepicker.js"></script>
     <script src="/assets/global/js/Plugin/dropify.js"></script>
     <script>
-      $('.input-daterange>input').datepicker({
-        format: 'yyyy-mm-dd',
-      });
+        @if(old('type'))
+        $(document).ready(function() {
+          $("input[name='type'][value='{{old('type')}}']").click();
+        });
+        @endif
 
-      $('input[name=\'type\']').change(function() {
-        if ($(this).val() === '2') {
-          $('#rule').attr('required', true);
-          $('.discount').show();
-          $('.usage').show();
-          $('.amount').hide();
-        } else if ($(this).val() === '3') {
-          $('#rule').attr('required', false);
-          $('.discount').hide();
-          $('.usage').hide();
-          $('.amount').show();
-        } else {
-          $('#rule').attr('required', true);
-          $('.discount').hide();
-          $('.usage').show();
-          $('.amount').show();
-        }
-      });
+        $('.input-daterange>input').datepicker({
+          format: 'yyyy-mm-dd',
+        });
+
+        $('input[name=\'type\']').change(function() {
+          if ($(this).val() === '2') {
+            $('#rule').attr('required', true);
+            $('.discount').show();
+            $('.usage').show();
+            $('.amount').hide();
+          } else if ($(this).val() === '3') {
+            $('#rule').attr('required', false);
+            $('.discount').hide();
+            $('.usage').hide();
+            $('.amount').show();
+          } else {
+            $('#rule').attr('required', true);
+            $('.discount').hide();
+            $('.usage').show();
+            $('.amount').show();
+          }
+        });
     </script>
 @endsection

+ 1 - 1
resources/views/admin/coupon/index.blade.php

@@ -79,7 +79,7 @@
                             <td>
                                 {{$coupon->value}}@if($coupon->type === 2)%@else元@endif
                             </td>
-                            <td> {{date('Y-m-d', $coupon->start_time)}} ~ {{date('Y-m-d', $coupon->end_time)}} </td>
+                            <td> {{$coupon->start_time}} ~ {{$coupon->end_time}} </td>
                             <td>
                                 @if($coupon->status === 1)
                                     <span class="badge badge-lg badge-default"> 已使用 </span>

+ 13 - 0
resources/views/admin/index.blade.php

@@ -37,6 +37,19 @@
                         </div>
                     </a>
                 </div>
+                <div class="col-xl-3 col-md-6 info-panel">
+                    <a href="{{route('admin.user.index', ['paying'=>1])}}" class="card card-shadow">
+                        <div class="card-block bg-white">
+                            <button type="button" class="btn btn-floating btn-sm btn-info">
+                                <i class="icon md-money-box"></i>
+                            </button>
+                            <span class="ml-15 font-weight-400">付费用户</span>
+                            <div class="content-text text-center mb-0">
+                                <span class="font-size-40 font-weight-100">{{$payingUserCount}}</span>
+                            </div>
+                        </div>
+                    </a>
+                </div>
                 <div class="col-xl-3 col-md-6 info-panel">
                     <a href="{{route('admin.user.index', ['active'=>1])}}" class="card card-shadow">
                         <div class="card-block bg-white">

+ 11 - 11
resources/views/admin/logs/callback.blade.php

@@ -55,21 +55,21 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($callbackLogs as $log)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->type_label}} </td>
-                            <td> {{$vo->trade_no}} </td>
+                            <td> {{$log->id}} </td>
+                            <td> {{$log->type_label}} </td>
+                            <td> {{$log->trade_no}} </td>
                             <td>
                                 @can('admin.order')
-                                    <a href="{{route('admin.order', ['order_sn' => $vo->out_trade_no])}}" target="_blank"> {{$vo->out_trade_no}} </a>
+                                    <a href="{{route('admin.order', ['order_sn' => $log->out_trade_no])}}" target="_blank"> {{$log->out_trade_no}} </a>
                                 @else
-                                    {{$vo->out_trade_no}}
+                                    {{$log->out_trade_no}}
                                 @endcan
                             </td>
-                            <td> {{$vo->amount}}元</td>
-                            <td> {!! $vo->trade_status_label !!} </td>
-                            <td> {{$vo->created_at}} </td>
+                            <td> {{$log->amount}}元</td>
+                            <td> {!! $log->trade_status_label !!} </td>
+                            <td> {{$log->created_at}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -78,11 +78,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 个账号
+                        共 <code>{{$callbackLogs->total()}}</code> 个账号
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$callbackLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 12 - 12
resources/views/admin/logs/notification.blade.php

@@ -41,18 +41,18 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($notificationLogs as $log)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->type === 1 ? 'Email' : ($vo->type === 2? 'ServerChan': 'Bark')}} </td>
-                            <td> {{$vo->address}} </td>
-                            <td> {{$vo->title}} </td>
-                            <td> {{$vo->content}} </td>
-                            <td> {{$vo->created_at}} </td>
+                            <td> {{$log->id}} </td>
+                            <td> {{$log->type === 1 ? 'Email' : ($log->type === 2? 'ServerChan': 'Bark')}} </td>
+                            <td> {{$log->address}} </td>
+                            <td> {{$log->title}} </td>
+                            <td> {{$log->content}} </td>
+                            <td> {{$log->created_at}} </td>
                             <td>
-                                @if($vo->status < 0)
-                                    <span class="badge badge-danger"> {{Str::limit($vo->error)}} </span>
-                                @elseif($vo->status > 0)
+                                @if($log->status < 0)
+                                    <span class="badge badge-danger"> {{Str::limit($log->error)}} </span>
+                                @elseif($log->status > 0)
                                     <labe class="badge badge-success">投递成功</labe>
                                 @else
                                     <span class="badge badge-default"> 等待投递 </span>
@@ -66,11 +66,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条记录
+                        共 <code>{{$notificationLogs->total()}}</code> 条记录
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$notificationLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 13 - 13
resources/views/admin/logs/onlineIPMonitor.blade.php

@@ -31,7 +31,7 @@
                     <div class="form-group col-lg-2 col-sm-5">
                         <select name="nodeId" id="nodeId" class="form-control" onChange="Search()">
                             <option value="" @if(Request::input('nodeId') == '') selected @endif hidden>选择节点</option>
-                            @foreach($nodeList as $node)
+                            @foreach($nodes as $node)
                                 <option value="{{$node->id}}"
                                         @if(Request::input('nodeId') == $node->id) selected @endif>{{$node->name}}</option>
                             @endforeach
@@ -55,23 +55,23 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($onlineIPLogs as $log)
                         <tr>
-                            <td>{{$vo->id}}</td>
-                            <td>{{$vo->type}}</td>
-                            <td>{{$vo->node ? $vo->node->name : '【节点已删除】'}}</td>
-                            <td>{{$vo->user ? $vo->user->email : '【用户已删除】'}}</td>
+                            <td>{{$log->id}}</td>
+                            <td>{{$log->type}}</td>
+                            <td>{{$log->node ? $log->node->name : '【节点已删除】'}}</td>
+                            <td>{{$log->user ? $log->user->email : '【用户已删除】'}}</td>
                             <td>
-                                @if (strpos($vo->ip, ',') !== false)
-                                    @foreach (explode(',', $vo->ip) as $ip)
+                                @if (strpos($log->ip, ',') !== false)
+                                    @foreach (explode(',', $log->ip) as $ip)
                                         <a href="https://www.ipip.net/ip/{{$ip}}.html" target="_blank">{{$ip}}</a>
                                     @endforeach
                                 @else
-                                    <a href="https://www.ipip.net/ip/{{$vo->ip}}.html" target="_blank">{{$vo->ip}}</a>
+                                    <a href="https://www.ipip.net/ip/{{$log->ip}}.html" target="_blank">{{$log->ip}}</a>
                                 @endif
                             </td>
-                            <td>{{strpos($vo->ip, ',') !== false? '':$vo->ipInfo}}</td>
-                            <td>{{date('Y-m-d H:i:s',$vo->created_at)}}</td>
+                            <td>{{strpos($log->ip, ',') !== false? '':$log->ipInfo}}</td>
+                            <td>{{date('Y-m-d H:i:s',$log->created_at)}}</td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -80,11 +80,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 个账号
+                        共 <code>{{$onlineIPLogs->total()}}</code> 个账号
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$onlineIPLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 3 - 3
resources/views/admin/logs/order.blade.php

@@ -99,7 +99,7 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($orderList as $order)
+                    @foreach($orders as $order)
                         <tr>
                             <td> {{$order->id}} </td>
                             <td>
@@ -142,11 +142,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$orderList->total()}}</code> 个订单
+                        共 <code>{{$orders->total()}}</code> 个订单
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$orderList->links()}}
+                            {{$orders->links()}}
                         </nav>
                     </div>
                 </div>

+ 14 - 14
resources/views/admin/logs/traffic.blade.php

@@ -23,7 +23,7 @@
                     <div class="form-group col-lg-3 col-sm-8">
                         <select class="form-control" name="nodeId" id="nodeId" onChange="Search()">
                             <option value="" @if(Request::input('nodeId') == '') selected @endif hidden>选择节点</option>
-                            @foreach($nodeList as $node)
+                            @foreach($nodes as $node)
                                 <option value="{{$node->id}}" @if(Request::input('nodeId') == $node->id) selected @endif>
                                     {{$node->name}}
                                 </option>
@@ -64,26 +64,26 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($dataFlowLogs as $log)
                         <tr>
-                            <td> {{$vo->id}} </td>
+                            <td> {{$log->id}} </td>
                             <td>
-                                @if(empty($vo->user))
+                                @if(empty($log->user))
                                     【账号已删除】
                                 @else
                                     @can('admin.user.index')
-                                        <a href="{{route('admin.user.index', ['id' => $vo->user->id])}}" target="_blank"> {{$vo->user->email}} </a>
+                                        <a href="{{route('admin.user.index', ['id' => $log->user->id])}}" target="_blank"> {{$log->user->email}} </a>
                                     @else
-                                        {{$vo->user->email}}
+                                        {{$log->user->email}}
                                     @endcan
                                 @endif
                             </td>
-                            <td> {{$vo->node->name ?? '【节点已删除】'}} </td>
-                            <td> {{$vo->rate}} </td>
-                            <td> {{$vo->u}} </td>
-                            <td> {{$vo->d}} </td>
-                            <td><span class="badge badge-danger"> {{$vo->traffic}} </span></td>
-                            <td> {{$vo->log_time}} </td>
+                            <td> {{$log->node->name ?? '【节点已删除】'}} </td>
+                            <td> {{$log->rate}} </td>
+                            <td> {{$log->u}} </td>
+                            <td> {{$log->d}} </td>
+                            <td><span class="badge badge-danger"> {{$log->traffic}} </span></td>
+                            <td> {{$log->log_time}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -92,11 +92,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-6">
-                        共 <code>{{$list->total()}} 条记录</code>,合计 <code>{{$totalTraffic}}</code>
+                        共 <code>{{$dataFlowLogs->total()}} 条记录</code>,合计 <code>{{$totalTraffic}}</code>
                     </div>
                     <div class="col-sm-6">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$dataFlowLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 11 - 11
resources/views/admin/logs/userBanHistory.blade.php

@@ -30,26 +30,26 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($userBanLogs as $log)
                         <tr>
                             <td>
-                                {{$vo->id}}
+                                {{$log->id}}
                             </td>
                             <td>
-                                @if ($vo->user)
+                                @if ($log->user)
                                     @can('admin.user.index')
-                                        <a href="{{route('admin.user.index', ['email'=>$vo->user->email])}}" target="_blank"> {{$vo->user->email}}</a>
+                                        <a href="{{route('admin.user.index', ['email'=>$log->user->email])}}" target="_blank"> {{$log->user->email}}</a>
                                     @else
-                                        {{$vo->user->email}}
+                                        {{$log->user->email}}
                                     @endcan
                                 @else
                                     【账号已删除】
                                 @endif
                             </td>
-                            <td> {{$vo->time}}分钟</td>
-                            <td> {{$vo->description}} </td>
-                            <td> {{$vo->created_at}} </td>
-                            <td> {{date("Y-m-d H:i:s", $vo->user->t)}} </td>
+                            <td> {{$log->time}}分钟</td>
+                            <td> {{$log->description}} </td>
+                            <td> {{$log->created_at}} </td>
+                            <td> {{date("Y-m-d H:i:s", $log->user->t)}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -58,11 +58,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条记录
+                        共 <code>{{$userBanLogs->total()}}</code> 条记录
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$userBanLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 12 - 12
resources/views/admin/logs/userCreditHistory.blade.php

@@ -32,22 +32,22 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($userCreditLogs as $log)
                         <tr>
-                            <td> {{$vo->id}} </td>
+                            <td> {{$log->id}} </td>
                             <td>
-                                @if(empty($vo->user))
+                                @if(empty($log->user))
                                     【账号已删除】
                                 @else
-                                    <a href="{{route('admin.log.credit', ['email'=>$vo->user->email])}}"> {{$vo->user->email}} </a>
+                                    <a href="{{route('admin.log.credit', ['email'=>$log->user->email])}}"> {{$log->user->email}} </a>
                                 @endif
                             </td>
-                            <td> {{$vo->order_id}} </td>
-                            <td> {{$vo->before}} </td>
-                            <td> {{$vo->amount}} </td>
-                            <td> {{$vo->after}} </td>
-                            <td> {{$vo->description}} </td>
-                            <td> {{$vo->created_at}} </td>
+                            <td> {{$log->order_id}} </td>
+                            <td> {{$log->before}} </td>
+                            <td> {{$log->amount}} </td>
+                            <td> {{$log->after}} </td>
+                            <td> {{$log->description}} </td>
+                            <td> {{$log->created_at}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -56,11 +56,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条记录
+                        共 <code>{{$userCreditLogs->total()}}</code> 条记录
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$userCreditLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 14 - 14
resources/views/admin/logs/userTraffic.blade.php

@@ -31,33 +31,33 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($userTrafficLogs as $log)
                         <tr>
-                            <td> {{$vo->id}} </td>
+                            <td> {{$log->id}} </td>
                             <td>
-                                @if(empty($vo->user))
+                                @if(empty($log->user))
                                     【账号已删除】
                                 @else
-                                    <a href="{{route('admin.log.flow', ['email' => $vo->user->email])}}"> {{$vo->user->email}} </a>
+                                    <a href="{{route('admin.log.flow', ['email' => $log->user->email])}}"> {{$log->user->email}} </a>
                                 @endif
                             </td>
                             <td>
-                                @if ($vo->order_id)
-                                    @if($vo->order)
+                                @if ($log->order_id)
+                                    @if($log->order)
                                         @can('admin.order')
-                                            <a href="{{route('admin.order', ['id' => $vo->order_id])}}"></a>
+                                            <a href="{{route('admin.order', ['id' => $log->order_id])}}"></a>
                                         @else
-                                            {{$vo->order->goods->name}}
+                                            {{$log->order->goods->name}}
                                         @endcan
                                     @else
                                         【订单已删除】
                                     @endif
                                 @endif
                             </td>
-                            <td> {{$vo->before}} </td>
-                            <td> {{$vo->after}} </td>
-                            <td> {{$vo->description}} </td>
-                            <td> {{$vo->created_at}} </td>
+                            <td> {{$log->before}} </td>
+                            <td> {{$log->after}} </td>
+                            <td> {{$log->description}} </td>
+                            <td> {{$log->created_at}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -66,11 +66,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条记录
+                        共 <code>{{$userTrafficLogs->total()}}</code> 条记录
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$userTrafficLogs->links()}}
                         </nav>
                     </div>
                 </div>

+ 9 - 9
resources/views/admin/marketing/emailList.blade.php

@@ -38,14 +38,14 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($emails as $email)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->title}} </td>
-                            <td> {{$vo->content}} </td>
-                            <td> {{$vo->status_label}} </td>
-                            <td> {{$vo->created_at}} </td>
-                            <td> {{$vo->error}} </td>
+                            <td> {{$email->id}} </td>
+                            <td> {{$email->title}} </td>
+                            <td> {{$email->content}} </td>
+                            <td> {{$email->status_label}} </td>
+                            <td> {{$email->created_at}} </td>
+                            <td> {{$email->error}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -54,11 +54,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条消息
+                        共 <code>{{$emails->total()}}</code> 条消息
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$emails->links()}}
                         </nav>
                     </div>
                 </div>

+ 9 - 9
resources/views/admin/marketing/pushList.blade.php

@@ -47,14 +47,14 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach($list as $vo)
+                    @foreach($pushes as $push)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->title}} </td>
-                            <td> {{$vo->content}} </td>
-                            <td> {{$vo->status_label}} </td>
-                            <td> {{$vo->created_at}} </td>
-                            <td> {{$vo->error}} </td>
+                            <td> {{$push->id}} </td>
+                            <td> {{$push->title}} </td>
+                            <td> {{$push->content}} </td>
+                            <td> {{$push->status_label}} </td>
+                            <td> {{$push->created_at}} </td>
+                            <td> {{$push->error}} </td>
                         </tr>
                     @endforeach
                     </tbody>
@@ -63,11 +63,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条推送消息
+                        共 <code>{{$pushes->total()}}</code> 条推送消息
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$pushes->links()}}
                         </nav>
                     </div>
                 </div>

+ 30 - 30
resources/views/admin/node/auth.blade.php

@@ -31,28 +31,28 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach ($list as $vo)
+                    @foreach ($authorizations as $auth)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->node_id}} </td>
-                            <td> {{$vo->node->type_label}} </td>
-                            <td> {{Str::limit($vo->node->name, 20) ?? '【节点已删除】'}} </td>
-                            <td> {{$vo->node->server ?? '【节点已删除】'}} </td>
-                            <td> {{$vo->node->ip ?? '【节点已删除】'}} </td>
-                            <td><span class="badge badge-lg badge-info"> {{$vo->key}} </span></td>
-                            <td><span class="badge badge-lg badge-info"> {{$vo->secret}} </span></td>
+                            <td> {{$auth->id}} </td>
+                            <td> {{$auth->node_id}} </td>
+                            <td> {{$auth->node->type_label}} </td>
+                            <td> {{Str::limit($auth->node->name, 20) ?? '【节点已删除】'}} </td>
+                            <td> {{$auth->node->server ?? '【节点已删除】'}} </td>
+                            <td> {{$auth->node->ip ?? '【节点已删除】'}} </td>
+                            <td><span class="badge badge-lg badge-info"> {{$auth->key}} </span></td>
+                            <td><span class="badge badge-lg badge-info"> {{$auth->secret}} </span></td>
                             <td>
                                 <div class="btn-group">
-                                    <button data-target="#install_{{$vo->node->type}}_{{$vo->id}}" data-toggle="modal" class="btn btn-primary">
+                                    <button data-target="#install_{{$auth->node->type}}_{{$auth->id}}" data-toggle="modal" class="btn btn-primary">
                                         <i class="icon wb-code" aria-hidden="true"></i>部署后端
                                     </button>
                                     @can('admin.node.auth.update')
-                                        <button onclick="refreshAuth('{{$vo->id}}')" class="btn btn-danger">
+                                        <button onclick="refreshAuth('{{$auth->id}}')" class="btn btn-danger">
                                             <i class="icon wb-reload" aria-hidden="true"></i> 重置密钥
                                         </button>
                                     @endcan
                                     @can('admin.node.auth.destroy')
-                                        <button onclick="deleteAuth('{{$vo->id}}')" class="btn btn-primary">
+                                        <button onclick="deleteAuth('{{$auth->id}}')" class="btn btn-primary">
                                             <i class="icon wb-trash" aria-hidden="true"></i> 删除
                                         </button>
                                     @endcan
@@ -66,11 +66,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 条授权
+                        共 <code>{{$authorizations->total()}}</code> 条授权
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$authorizations->links()}}
                         </nav>
                     </div>
                 </div>
@@ -78,8 +78,8 @@
         </div>
     </div>
 
-    @foreach($list as $vl)
-        <div id="install_{{$vl->node->type}}_{{$vl->id}}" class="modal fade" tabindex="-1" data-focus-on="input:first" data-keyboard="false">
+    @foreach($authorizations as $auth)
+        <div id="install_{{$auth->node->type}}_{{$auth->id}}" class="modal fade" tabindex="-1" data-focus-on="input:first" data-keyboard="false">
             <div class="modal-dialog modal-simple modal-center modal-lg">
                 <div class="modal-content">
                     <div class="modal-header">
@@ -87,18 +87,18 @@
                             <span aria-hidden="true">×</span>
                         </button>
                         <h4 class="modal-title">
-                            部署 {{$vl->node->type_label}} 后端
+                            部署 {{$auth->node->type_label}} 后端
                         </h4>
                     </div>
                     <div class="modal-body">
-                        @if($vl->node->type === 2)
+                        @if($auth->node->type === 2)
                             <div class="alert alert-info text-break">
                                 <div class="text-center red-700 mb-5">VNET-V2Ray</div>
                                 (yum install curl 2> /dev/null || apt install curl 2> /dev/null) \<br>
                                 && curl -L -s https://bit.ly/3oO3HZy \<br>
                                 | WEB_API="{{sysConfig('web_api_url') ?: sysConfig('website_url')}}" \<br>
-                                NODE_ID={{$vl->node->id}} \<br>
-                                NODE_KEY={{$vl->key}} \<br>
+                                NODE_ID={{$auth->node->id}} \<br>
+                                NODE_KEY={{$auth->key}} \<br>
                                 bash
                                 <br>
                                 <br>
@@ -122,8 +122,8 @@
                                 (yum install curl 2> /dev/null || apt install curl 2> /dev/null) \<br>
                                 && curl -L -s https://bit.ly/2HswWko \<br>
                                 | WEB_API="{{sysConfig('web_api_url') ?: sysConfig('website_url')}}" \<br>
-                                NODE_ID={{$vl->node->id}} \<br>
-                                NODE_KEY={{$vl->key}} \<br>
+                                NODE_ID={{$auth->node->id}} \<br>
+                                NODE_KEY={{$auth->key}} \<br>
                                 bash
                                 <br>
                                 <br>
@@ -142,9 +142,9 @@
                                 <br>
                                 实时日志:journalctl -u v2ray -f
                             </div>
-                        @elseif($vl->node->type === 3)
-                            @if(!$vl->node->server)
-                                <h3>请先<a href="{{route('admin.node.edit', $vl->node)}}" target="_blank">填写节点域名</a>并将域名解析到节点对应的IP上
+                        @elseif($auth->node->type === 3)
+                            @if(!$auth->node->server)
+                                <h3>请先<a href="{{route('admin.node.edit', $auth->node)}}" target="_blank">填写节点域名</a>并将域名解析到节点对应的IP上
                                 </h3>
                             @else
                                 <div class="alert alert-info text-break">
@@ -152,9 +152,9 @@
                                     (yum install curl 2> /dev/null || apt install curl 2> /dev/null) \<br>
                                     && curl -L -s http://mrw.so/6cMfGy \<br>
                                     | WEB_API="{{sysConfig('web_api_url') ?: sysConfig('website_url')}}" \<br>
-                                    NODE_ID={{$vl->node->id}} \<br>
-                                    NODE_KEY={{$vl->key}} \<br>
-                                    NODE_HOST={{$vl->node->server}} \<br>
+                                    NODE_ID={{$auth->node->id}} \<br>
+                                    NODE_KEY={{$auth->key}} \<br>
+                                    NODE_HOST={{$auth->node->server}} \<br>
                                     bash
                                     <br>
                                     <br>
@@ -180,8 +180,8 @@
                                 (yum install curl 2> /dev/null || apt install curl 2> /dev/null) \<br>
                                 && curl -L -s https://bit.ly/3828OP1 \<br>
                                 | WEB_API="{{sysConfig('web_api_url') ?: sysConfig('website_url')}}" \<br>
-                                NODE_ID={{$vl->node->id}} \<br>
-                                NODE_KEY={{$vl->key}} \<br>
+                                NODE_ID={{$auth->node->id}} \<br>
+                                NODE_KEY={{$auth->key}} \<br>
                                 bash
                                 <br>
                                 <br>

+ 12 - 12
resources/views/admin/node/cert/index.blade.php

@@ -30,25 +30,25 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach ($list as $vo)
+                    @foreach ($certs as $cert)
                         <tr>
-                            <td> {{$vo->id}} </td>
-                            <td> {{$vo->domain}} </td>
-                            <td> {{$vo->key ? '✔️' : '❌'}} </td>
-                            <td> {{$vo->pem ? '✔️' : '❌'}} </td>
-                            <td> {{$vo->issuer}} </td>
-                            <td> {{$vo->from}} </td>
-                            <td> {{$vo->to}} </td>
+                            <td> {{$cert->id}} </td>
+                            <td> {{$cert->domain}} </td>
+                            <td> {{$cert->key ? '✔️' : '❌'}} </td>
+                            <td> {{$cert->pem ? '✔️' : '❌'}} </td>
+                            <td> {{$cert->issuer}} </td>
+                            <td> {{$cert->from}} </td>
+                            <td> {{$cert->to}} </td>
                             <td>
                                 @canany(['admin.node.cert.edit', 'admin.node.cert.destroy'])
                                     <div class="btn-group">
                                         @can('admin.node.cert.edit')
-                                            <a href="{{route('admin.node.cert.edit', $vo->id)}}" class="btn btn-primary">
+                                            <a href="{{route('admin.node.cert.edit', $cert)}}" class="btn btn-primary">
                                                 <i class="icon wb-edit" aria-hidden="true"></i>
                                             </a>
                                         @endcan
                                         @can('admin.node.cert.destroy')
-                                            <button onclick="delCertificate('{{$vo->id}}')" class="btn btn-danger">
+                                            <button onclick="delCertificate('{{$cert->id}}')" class="btn btn-danger">
                                                 <i class="icon wb-trash" aria-hidden="true"></i>
                                             </button>
                                         @endcan
@@ -63,11 +63,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$list->total()}}</code> 个域名证书
+                        共 <code>{{$certs->total()}}</code> 个域名证书
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$list->links()}}
+                            {{$certs->links()}}
                         </nav>
                     </div>
                 </div>

+ 24 - 28
resources/views/admin/node/cert/info.blade.php

@@ -6,28 +6,37 @@
     <div class="page-content container">
         <div class="panel">
             <div class="panel-heading">
-                <h2 class="panel-title">@isset($Dv) 编辑 @else 添加 @endisset域名证书</h2>
+                <h2 class="panel-title">@isset($cert) 编辑 @else 添加 @endisset域名证书</h2>
             </div>
+            @if (Session::has('successMsg'))
+                <x-alert type="success" :message="Session::get('successMsg')"/>
+            @endif
+            @if($errors->any())
+                <x-alert type="danger" :message="$errors->all()"/>
+            @endif
             <div class="panel-body">
-                <form class="form-horizontal" onsubmit="return Submit()">
+                <form action="@isset($cert) {{route('admin.node.cert.update', $cert)}} @else {{route('admin.node.cert.store')}} @endisset"
+                      method="POST" enctype="multipart/form-data" class="form-horizontal">
+                    @isset($cert)@method('PUT')@endisset
+                    @csrf
                     <div class="form-group row">
                         <label for="domain" class="col-md-3 col-form-label">域名</label>
                         <div class="col-md-9">
-                            <input type="text" class="form-control" name="domain" id="domain" @isset($Dv) value="{{$Dv->domain}}" @endisset>
+                            <input type="text" class="form-control" name="domain" id="domain" required>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label for="key" class="col-md-3 col-form-label">Key</label>
                         <div class="col-md-9">
                             <textarea type="text" rows="10" class="form-control" name="key" id="key"
-                                      placeholder="域名证书的KEY值,允许为空,VNET-V2Ray后端支持自动签证书">@isset($Dv) {{$Dv->key}} @endisset</textarea>
+                                      placeholder="域名证书的KEY值,允许为空,VNET-V2Ray后端支持自动签证书"></textarea>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label for="pem" class="col-md-3 col-form-label">Pem</label>
                         <div class="col-md-9">
                             <textarea type="text" rows="10" class="form-control" name="pem" id="pem"
-                                      placeholder="域名证书的PEM值,允许为空,VNET-V2Ray后端支持自动签证书">@isset($Dv) {{$Dv->pem}} @endisset</textarea>
+                                      placeholder="域名证书的PEM值,允许为空,VNET-V2Ray后端支持自动签证书"></textarea>
                         </div>
                     </div>
                     <div class="form-actions">
@@ -40,28 +49,15 @@
 @endsection
 @section('javascript')
     <script>
-      // 添加域名证书
-      function Submit() {
-        $.ajax({
-          method: @isset($Dv) 'PUT' @else 'POST' @endisset,
-          url: @isset($Dv) '{{route('admin.node.cert.update', $Dv->id)}}' @else '{{route('admin.node.cert.store')}}' @endisset,
-          async: false,
-          data: {_token: '{{csrf_token()}}', domain: $('#domain').val(), key: $('#key').val(), pem: $('#pem').val()},
-          dataType: 'json',
-          success: function(ret) {
-            if (ret.status === 'success') {
-              swal.fire({
-                title: ret.message,
-                icon: 'success',
-                timer: 1000,
-                showConfirmButton: false,
-              }).then(() => window.location.href = '{{route('admin.node.cert.index')}}');
-            } else {
-              swal.fire({title: '[错误 | Error]', text: ret.message, icon: 'error'});
-            }
-          },
-        });
-        return false;
-      }
+      $(document).ready(function() {
+        $('#domain').val(@json(old('domain')));
+        $('#key').val(@json(old('key')));
+        $('#pem').val(@json(old('pem')));
+          @isset($cert)
+          $('#domain').val(@json(old('domain') ?? $cert->domain));
+        $('#key').val(@json(old('key') ?? $cert->key));
+        $('#pem').val(@json(old('pem') ?? $cert->pem));
+          @endisset
+      });
     </script>
 @endsection

+ 21 - 9
resources/views/admin/node/info.blade.php

@@ -67,12 +67,22 @@
                                     <div class="form-group row">
                                         <label for="level" class="col-md-3 col-form-label">等级</label>
                                         <select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control show-tick" id="level" name="level">
-                                            @foreach($levelList as $level)
+                                            @foreach($levels as $level)
                                                 <option value="{{$level->level}}">{{$level->name}}</option>
                                             @endforeach
                                         </select>
                                         <div class="text-help offset-md-3"> 等级:0-无等级,全部可见</div>
                                     </div>
+                                    <div class="form-group row">
+                                        <label for="ruleGroup" class="col-md-3 col-form-label">审计分组</label>
+                                        <select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control show-tick"
+                                                id="ruleGroup" name="ruleGroup">
+                                            <option value="">不使用</option>
+                                            @foreach($ruleGroups as $ruleGroup)
+                                                <option value="{{$ruleGroup->id}}">{{$ruleGroup->name}}</option>
+                                            @endforeach
+                                        </select>
+                                    </div>
                                     <div class="form-group row">
                                         <label for="speed_limit" class="col-md-3 col-form-label">节点限速</label>
                                         <div class="col-md-4 input-group p-0">
@@ -88,7 +98,7 @@
                                         <label for="labels" class="col-md-3 col-form-label">标签</label>
                                         <select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control show-tick" id="labels" name="labels"
                                                 multiple>
-                                            @foreach($labelList as $label)
+                                            @foreach($labels as $label)
                                                 <option value="{{$label->id}}">{{$label->name}}</option>
                                             @endforeach
                                         </select>
@@ -98,7 +108,7 @@
                                         <select data-plugin="selectpicker" data-style="btn-outline btn-primary"
                                                 class="col-md-5 form-control" name="country_code" id="country_code">
                                             <option value="un" selected hidden>请选择</option>
-                                            @foreach($countryList as $country)
+                                            @foreach($countries as $country)
                                                 <option value="{{$country->code}}">{{$country->code}} - {{$country->name}}</option>
                                             @endforeach
                                         </select>
@@ -285,10 +295,10 @@
                                                 <div name="v2_ws">
                                                     <select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="form-control" id="v2_ws">
                                                         <option value="" hidden></option>
-                                                        @foreach($dvList as $dv)
-                                                            <option value="{{$dv->domain}}"
-                                                                    @if(isset($node) && $node->v2_net === "ws" && $node->v2_host === $dv->domain) selected @endif>
-                                                                {{$dv->domain}}
+                                                        @foreach($certs as $cert)
+                                                            <option value="{{$cert->domain}}"
+                                                                    @if(isset($node) && $node->v2_net === "ws" && $node->v2_host === $cert->domain) selected @endif>
+                                                                {{$cert->domain}}
                                                             </option>
                                                         @endforeach
                                                     </select>
@@ -415,9 +425,10 @@
         $('#push_port').val('{{$node->push_port}}');
         $('#traffic_rate').val('{{$node->traffic_rate}}');
         $('#level').selectpicker('val', '{{$node->level}}');
+        $('#ruleGroup').selectpicker('val', '{{$node->rule_group_id}}');
         $('#speed_limit').val('{{$node->speed_limit}}');
         $('#client_limit').val('{{$node->client_limit}}');
-        $('#labels').selectpicker('val', {{$node->labels->pluck('label_id')}});
+        $('#labels').selectpicker('val', {{$node->labels->pluck('id')}});
         $('#country_code').selectpicker('val', '{{$node->country_code}}');
         $('#description').val('{{$node->description}}');
         $('#sort').val('{{$node->sort}}');
@@ -500,7 +511,7 @@
         }
         $.ajax({
           method: @isset($node) 'PUT' @else 'POST' @endisset,
-          url: '{{isset($node)? route('admin.node.update', $node->id) : route('admin.node.store')}}',
+          url: '{{isset($node)? route('admin.node.update', $node) : route('admin.node.store')}}',
           async: false,
           data: {
             _token: '{{csrf_token()}}',
@@ -512,6 +523,7 @@
             push_port: $('#push_port').val(),
             traffic_rate: $('#traffic_rate').val(),
             level: $('#level').val(),
+            rule_group_id: $('#ruleGroup').val(),
             speed_limit: $('#speed_limit').val(),
             client_limit: $('#client_limit').val(),
             labels: $('#labels').val(),

+ 10 - 8
resources/views/admin/permission/info.blade.php

@@ -22,14 +22,14 @@
                     <div class="form-group row">
                         <label class="col-md-2 col-sm-3 col-form-label" for="description">名称</label>
                         <div class="col-md-7 col-sm-8">
-                            <input type="text" class="form-control" name="description" id="description"/>
+                            <input type="text" class="form-control" name="description" id="description" required/>
                             <span class="text-help"> 填写名称,例:【A系统】编辑A </span>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label class="col-md-2 col-sm-3 col-form-label" for="name">行为</label>
                         <div class="col-md-7 col-sm-8">
-                            <input type="text" class="form-control" name="name" id="name"/>
+                            <input type="text" class="form-control" name="name" id="name" required/>
                             <span class="text-help"> 填写路由名称,例:admin.permission.create,update </span>
                         </div>
                     </div>
@@ -44,11 +44,13 @@
 @endsection
 @section('javascript')
     <script>
-        @isset($permission)
-        $(document).ready(function() {
-          $('#description').val('{{$permission->description}}');
-          $('#name').val('{{$permission->name}}');
-        });
-        @endisset
+      $(document).ready(function() {
+          @isset($permission)
+          $('#description').val(@json(old('description') ?? $permission->description));
+        $('#name').val(@json(old('name') ?? $permission->name));
+          @endisset
+          $('#description').val(@json(old('description')));
+        $('#name').val(@json(old('name')));
+      });
     </script>
 @endsection

+ 2 - 2
resources/views/admin/role/info.blade.php

@@ -30,14 +30,14 @@
                     <div class="form-group row">
                         <label class="col-md-2 col-sm-3 col-form-label" for="description">显示名称</label>
                         <div class="col-md-5 col-sm-9">
-                            <input type="text" class="form-control" name="description" id="description"/>
+                            <input type="text" class="form-control" name="description" id="description" required/>
                             <span class="text-help"> 名称,例如:管理员 </span>
                         </div>
                     </div>
                     <div class="form-group row">
                         <label class="col-md-2 col-sm-3 col-form-label" for="name">内部名称</label>
                         <div class="col-md-5 col-sm-9">
-                            <input type="text" class="form-control" name="name" id="name"/>
+                            <input type="text" class="form-control" name="name" id="name" required/>
                             <span class="text-help"> 名称,例如:Administrator </span>
                         </div>
                     </div>

+ 0 - 107
resources/views/admin/rule/group/assign.blade.php

@@ -1,107 +0,0 @@
-@extends('admin.layouts')
-@section('css')
-    <link href="/assets/global/vendor/multi-select/multi-select.min.css" rel="stylesheet">
-@endsection
-@section('content')
-    <div class="page-content container">
-        <div class="panel">
-            <div class="panel-heading">
-                <h2 class="panel-title">分配节点</h2>
-                <div class="panel-actions">
-                    <a href="{{route('admin.rule.group.index')}}" class="btn btn-danger">返 回</a>
-                </div>
-            </div>
-            @if (Session::has('successMsg'))
-                <x-alert type="success" :message="Session::get('successMsg')"/>
-            @endif
-            @if($errors->any())
-                <x-alert type="danger" :message="$errors->all()"/>
-            @endif
-            <div class="panel-body">
-                <form action={{route('admin.rule.group.assign', $ruleGroup)}} method="post" enctype="multipart/form-data" class="form-horizontal">
-                    @method('PUT')@csrf
-                    <div class="form-group row">
-                        <label class="col-md-2 col-sm-3 col-form-label" for="name">所属分组</label>
-                        <div class="col-auto">
-                            <input class="form-control" id="name" value="{{$ruleGroup->name}}" readonly/>
-                        </div>
-                    </div>
-                    <div class="form-group row">
-                        <label class="col-md-2 col-sm-3 col-form-label" for="nodes">选择节点</label>
-                        <div class="col-md-9 col-sm-9">
-                            <div class="btn-group mb-20">
-                                <button type="button" class="btn btn-primary" id="select-all">全 选</button>
-                                <button type="button" class="btn btn-danger" id="deselect-all">清 空</button>
-                            </div>
-                            <select class="form-control" name="nodes[]" id="nodes" data-plugin="multiSelect" multiple>
-                                @foreach($nodeList as $node)
-                                    <option value="{{$node->id}}">{{$node->id . ' - ' . Str::limit($node->name, 30)}}</option>
-                                @endforeach
-                            </select>
-                        </div>
-                    </div>
-                    <div class="form-actions text-right">
-                        <button type="submit" class="btn btn-success">提 交</button>
-                    </div>
-                </form>
-            </div>
-        </div>
-    </div>
-@endsection
-@section('javascript')
-    <script src="/assets/global/vendor/multi-select/jquery.multi-select.min.js"></script>
-    <script src="/assets/global/js/Plugin/multi-select.js"></script>
-    <script src="/assets/custom/jquery.quicksearch.min.js"></script>
-    <script>
-      $(document).ready(function() {
-        $('#nodes').multiSelect('select',@json($ruleGroup->nodes));
-      });
-
-      // 权限列表
-      $('#nodes').multiSelect({
-        selectableHeader: '<input type=\'text\' class=\'search-input form-control\' autocomplete=\'off\' placeholder=\'待分配节点,此处可搜索\'>',
-        selectionHeader: '<input type=\'text\' class=\'search-input form-control\' autocomplete=\'off\' placeholder=\'已分配节点,此处可搜索\'>',
-        afterInit: function() {
-          const that = this,
-              $selectableSearch = that.$selectableUl.prev(),
-              $selectionSearch = that.$selectionUl.prev(),
-              selectableSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selectable:not(.ms-selected)',
-              selectionSearchString = '#' + that.$container.attr('id') + ' .ms-elem-selection.ms-selected';
-
-          that.qs1 = $selectableSearch.quicksearch(selectableSearchString).on('keydown', function(e) {
-            if (e.which === 40) {
-              that.$selectableUl.focus();
-              return false;
-            }
-          });
-
-          that.qs2 = $selectionSearch.quicksearch(selectionSearchString).on('keydown', function(e) {
-            if (e.which === 40) {
-              that.$selectionUl.focus();
-              return false;
-            }
-          });
-        },
-        afterSelect: function() {
-          this.qs1.cache();
-          this.qs2.cache();
-        },
-        afterDeselect: function() {
-          this.qs1.cache();
-          this.qs2.cache();
-        },
-      });
-
-      // 全选
-      $('#select-all').click(function() {
-        $('#nodes').multiSelect('select_all');
-        return false;
-      });
-
-      // 反选
-      $('#deselect-all').click(function() {
-        $('#nodes').multiSelect('deselect_all');
-        return false;
-      });
-    </script>
-@endsection

+ 6 - 11
resources/views/admin/rule/group/index.blade.php

@@ -26,26 +26,21 @@
                     </tr>
                     </thead>
                     <tbody>
-                    @foreach ($ruleGroupList as $ruleGroup)
+                    @foreach ($ruleGroups as $ruleGroup)
                         <tr>
                             <td> {{$ruleGroup->id}} </td>
                             <td> {{$ruleGroup->name}} </td>
                             <td> {!! $ruleGroup->type_label !!} </td>
                             <td>
-                                @canany(['admin.rule.group.editNode', 'admin.rule.group.edit', 'admin.rule.group.destroy'])
+                                @canany(['admin.rule.group.edit', 'admin.rule.group.destroy'])
                                     <div class="btn-group">
-                                        @can('admin.rule.group.editNode')
-                                            <a href="{{route('admin.rule.group.editNode', $ruleGroup->id)}}" class="btn btn-sm btn-outline-primary">
-                                                <i class="icon wb-plus" aria-hidden="true"></i>分配节点
-                                            </a>
-                                        @endcan
                                         @can('admin.rule.group.edit')
-                                            <a href="{{route('admin.rule.group.edit', $ruleGroup->id)}}" class="btn btn-sm btn-outline-primary">
+                                            <a href="{{route('admin.rule.group.edit', $ruleGroup)}}" class="btn btn-sm btn-outline-primary">
                                                 <i class="icon wb-edit"></i>编辑
                                             </a>
                                         @endcan
                                         @can('admin.rule.group.destroy')
-                                            <button onclick="delRuleGroup('{{route('admin.rule.group.destroy', $ruleGroup->id)}}', '{{$ruleGroup->name}}')"
+                                            <button onclick="delRuleGroup('{{route('admin.rule.group.destroy', $ruleGroup)}}', '{{$ruleGroup->name}}')"
                                                     class="btn btn-sm btn-outline-danger">
                                                 <i class="icon wb-trash"></i>删除
                                             </button>
@@ -61,11 +56,11 @@
             <div class="panel-footer">
                 <div class="row">
                     <div class="col-sm-4">
-                        共 <code>{{$ruleGroupList->total()}}</code> 个分组
+                        共 <code>{{$ruleGroups->total()}}</code> 个分组
                     </div>
                     <div class="col-sm-8">
                         <nav class="Page navigation float-right">
-                            {{$ruleGroupList->links()}}
+                            {{$ruleGroups->links()}}
                         </nav>
                     </div>
                 </div>

+ 3 - 3
resources/views/admin/rule/group/info.blade.php

@@ -18,7 +18,7 @@
                 <x-alert type="danger" :message="$errors->all()"/>
             @endif
             <div class="panel-body">
-                <form action="{{isset($ruleGroup) ? route('admin.rule.group.update', $ruleGroup->id) : route('admin.rule.group.store')}}" method="post"
+                <form action="{{isset($ruleGroup) ? route('admin.rule.group.update', $ruleGroup) : route('admin.rule.group.store')}}" method="post"
                       enctype="multipart/form-data" class="form-horizontal">
                     @isset($ruleGroup)@method('PUT')@endisset @csrf
                     <div class="form-group row">
@@ -54,7 +54,7 @@
                                 <button type="button" class="btn btn-danger" id="deselect-all">清 空</button>
                             </div>
                             <select class="form-control" name="rules[]" id="rules" data-plugin="multiSelect" multiple>
-                                @foreach($ruleList as $rule)
+                                @foreach($rules as $rule)
                                     <option value="{{$rule->id}}">{{$rule->id . ' - ' . $rule->name}}</option>
                                 @endforeach
                             </select>
@@ -77,7 +77,7 @@
         $(document).ready(function() {
           $('#name').val('{{$ruleGroup->name}}');
           $("input[name='type'][value='{{$ruleGroup->type}}']").click();
-          $('#rules').multiSelect('select',@json($ruleGroup->rules));
+          $('#rules').multiSelect('select', @json(array_map('strval', $ruleGroup->rules()->get()->pluck('id')->toArray())));
         });
         @endisset
         // 权限列表

Some files were not shown because too many files changed in this diff