1
0
BrettonYe 2 жил өмнө
parent
commit
4cfb0b4650

+ 1 - 1
app/Console/Commands/TaskHourly.php

@@ -33,7 +33,7 @@ class TaskHourly extends Command
         $end = strtotime($created_at);
         $start = $end - 3599;
         $data_anomaly_notification = sysConfig('data_anomaly_notification');
-        $traffic_ban_value = (int) sysConfig('traffic_ban_value') * GB;
+        $traffic_ban_value = (int) sysConfig('traffic_ban_value') * GiB;
         User::activeUser()->with('dataFlowLogs')->WhereHas('dataFlowLogs')->whereHas('dataFlowLogs', function (Builder $query) use ($start, $end) {
             $query->whereBetween('log_time', [$start, $end]);
         })->chunk(config('tasks.chunk'), function ($users) use ($traffic_ban_value, $start, $end, $created_at, $data_anomaly_notification) {

+ 4 - 4
app/Helpers/DataChart.php

@@ -38,16 +38,16 @@ trait DataChart
 
         // 节点一天内的流量
         foreach ($hourlyFlow as $date => $dataFlow) {
-            $hourlyData[$date] = round($dataFlow / GB, 3);
+            $hourlyData[$date] = round($dataFlow / GiB, 3);
         }
-        $hourlyData[$lastHour] = round($currentFlow / GB, 3);
+        $hourlyData[$lastHour] = round($currentFlow / GiB, 3);
 
         // 节点一个月内的流量
         foreach ($dailyFlow as $date => $dataFlow) {
-            $dailyData[$date - 1] = round($dataFlow / GB, 3);
+            $dailyData[$date - 1] = round($dataFlow / GiB, 3);
         }
 
-        $dailyData[$lastDay - 1] = round(array_sum($hourlyData) + $currentFlow / GB, 3);
+        $dailyData[$lastDay - 1] = round(array_sum($hourlyData) + $currentFlow / GiB, 3);
 
         return [
             'trafficDaily' => $dailyData,

+ 3 - 3
app/Http/Controllers/Admin/ReportController.php

@@ -11,7 +11,7 @@ class ReportController extends Controller
 {
     public function accounting()
     {
-        $orders = Order::where('status', '>=', 2)->whereHas('goods')->latest()->get(['created_at', 'amount']);
+        $orders = Order::where('status', '>=', 2)->has('goods')->latest()->get(['created_at', 'amount']);
         $ordersByDay = $orders->groupBy(function ($item) {
             return $item->created_at->format('Y-m-d');
         })->map(function ($row) {
@@ -85,7 +85,7 @@ class ReportController extends Controller
                     return [
                         'node_id' => $item->node_id,
                         'date' => (int) $item->date,
-                        'total' => round($item->total / GB, 2),
+                        'total' => round($item->total / GiB, 2),
                     ];
                 })->toArray();
 
@@ -99,7 +99,7 @@ class ReportController extends Controller
                     return [
                         'node_id' => $item->node_id,
                         'date' => (int) $item->date,
-                        'total' => round($item->total / GB, 2),
+                        'total' => round($item->total / GiB, 2),
                     ];
                 })->toArray();
         }

+ 2 - 2
app/Http/Controllers/Admin/RuleController.php

@@ -61,7 +61,7 @@ class RuleController extends Controller
     // 用户触发审计规则日志
     public function ruleLogList(Request $request)
     {
-        $query = RuleLog::query();
+        $query = RuleLog::with(['node:id,name', 'user:id,username', 'rule:id,name']);
 
         foreach (['user_id', 'node_id', 'rule_id'] as $field) {
             $request->whenFilled($field, function ($value) use ($query, $field) {
@@ -78,7 +78,7 @@ class RuleController extends Controller
         return view('admin.rule.log', [
             'nodes' => Node::all(),
             'rules' => Rule::all(),
-            'ruleLogs' => $query->with('node:id,name', 'user:id,username', 'rule:id,name')->latest()->paginate(15)->appends($request->except('page')),
+            'ruleLogs' => $query->latest()->paginate(15)->appends($request->except('page')),
         ]);
     }
 

+ 2 - 2
app/Http/Controllers/Admin/TicketController.php

@@ -21,7 +21,7 @@ class TicketController extends Controller
     {
         $query = Ticket::where(function ($query) {
             $query->whereAdminId(Auth::id())->orwhere('admin_id');
-        });
+        })->with('user');
 
         $request->whenFilled('username', function ($username) use ($query) {
             $query->whereHas('user', function ($query) use ($username) {
@@ -29,7 +29,7 @@ class TicketController extends Controller
             });
         });
 
-        return view('admin.ticket.index', ['ticketList' => $query->with('user')->latest()->paginate(10)->appends($request->except('page'))]);
+        return view('admin.ticket.index', ['ticketList' => $query->latest()->paginate(10)->appends($request->except('page'))]);
     }
 
     // 创建工单

+ 4 - 4
app/Http/Controllers/Admin/UserController.php

@@ -92,7 +92,7 @@ class UserController extends Controller
         $data['passwd'] = $data['passwd'] ?? Str::random();
         $data['vmess_id'] = $data['uuid'] ?? Str::uuid();
         Arr::forget($data, 'uuid');
-        $data['transfer_enable'] *= GB;
+        $data['transfer_enable'] *= GiB;
         $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('next year'));
         $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark'] ?? '');
         $data['reg_ip'] = IP::getClientIp();
@@ -176,8 +176,8 @@ class UserController extends Controller
     {
         try {
             for ($i = 0; $i < (int) request('amount', 1); $i++) {
-                $user = Helpers::addUser(Str::random(8).'@auto.generate', Str::random(), 1024 * GB, 365);
-                Helpers::addUserTrafficModifyLog($user->id, 0, 1024 * GB, trans('admin.user.massive.note'));
+                $user = Helpers::addUser(Str::random(8).'@auto.generate', Str::random(), 1024 * GiB, 365);
+                Helpers::addUserTrafficModifyLog($user->id, 0, 1024 * GiB, trans('admin.user.massive.note'));
             }
 
             return Response::json(['status' => 'success', 'message' => trans('admin.user.massive.succeed')]);
@@ -214,7 +214,7 @@ class UserController extends Controller
         $data['passwd'] = $request->input('passwd') ?? Str::random();
         $data['vmess_id'] = $data['uuid'] ?? Str::uuid();
         Arr::forget($data, ['roles', 'uuid', 'password']);
-        $data['transfer_enable'] *= GB;
+        $data['transfer_enable'] *= GiB;
         $data['enable'] = $data['status'] < 0 ? 0 : $data['enable'];
         $data['expired_at'] = $data['expired_at'] ?? date('Y-m-d', strtotime('next year'));
         $data['remark'] = str_replace(['atob', 'eval'], '', $data['remark']);

+ 4 - 4
app/Http/Controllers/Api/Client/ClientController.php

@@ -116,7 +116,7 @@ class ClientController extends Controller
             'keys' => [],
             'data' => [],
         ];
-        foreach (GoodsCategory::query()->whereStatus(1)->whereHas('goods')->get() as $category) {
+        foreach (GoodsCategory::query()->whereStatus(1)->with('goods')->has('goods')->get() as $category) {
             $shops['keys'][] = $category['name'];
             $shops['data'][$category['name']] = $category->goods()->get(['name', 'price', 'traffic'])->append('traffic_label')->toArray();
         }
@@ -128,7 +128,7 @@ class ClientController extends Controller
     {
         $user = auth()->user();
 
-        $referral_traffic = formatBytes(sysConfig('referral_traffic') * MB);
+        $referral_traffic = formatBytes(sysConfig('referral_traffic'), 'MiB');
         $referral_percent = sysConfig('referral_percent');
         // 邀请码
         $code = $user->invites()->whereStatus(0)->value('code');
@@ -146,7 +146,7 @@ class ClientController extends Controller
         // 累计数据
         $data['back_sum'] = ReferralLog::uid()->sum('commission') / 100;
         $data['user_num'] = $user->invitees()->count();
-        $data['list'] = $user->invitees()->whereHas('orders', function (Builder $query) {
+        $data['list'] = $user->invitees()->with('orders')->whereHas('orders', function (Builder $query) {
             $query->where('status', '>=', 2)->where('amount', '>', 0);
         })->selectRaw('username as user_name, UNIX_TIMESTAMP(created_at) as datetime, id')->orderByDesc('created_at')->limit(10)->get()->toArray();
         foreach ($data['list'] as &$item) {
@@ -169,7 +169,7 @@ class ClientController extends Controller
             return response()->json(['ret' => 0, 'title' => trans('common.success'), 'msg' => trans('user.home.attendance.done')]);
         }
 
-        $traffic = random_int((int) sysConfig('min_rand_traffic'), (int) sysConfig('max_rand_traffic')) * MB;
+        $traffic = random_int((int) sysConfig('min_rand_traffic'), (int) sysConfig('max_rand_traffic')) * MiB;
 
         if (! $user->incrementData($traffic)) {
             return response()->json(['ret' => 0, 'title' => trans('common.failed'), 'msg' => trans('user.home.attendance.failed')]);

+ 3 - 3
app/Http/Controllers/AuthController.php

@@ -227,7 +227,7 @@ class AuthController extends Controller
         $affArr = $this->getAff($invite_code, $aff);
         $inviter_id = $affArr['inviter_id'];
 
-        $transfer_enable = MB * ((int) sysConfig('default_traffic') + ($inviter_id ? (int) sysConfig('referral_traffic') : 0));
+        $transfer_enable = MiB * ((int) sysConfig('default_traffic') + ($inviter_id ? (int) sysConfig('referral_traffic') : 0));
 
         // 创建新用户
         if (! $user = Helpers::addUser($data['username'], $data['password'], $transfer_enable, sysConfig('default_days'), $inviter_id, $data['nickname'])) { // 注册失败,抛出异常
@@ -267,7 +267,7 @@ class AuthController extends Controller
             if ($inviter_id) {
                 $referralUser = User::find($inviter_id);
                 if ($referralUser && $referralUser->expiration_date >= date('Y-m-d')) {
-                    $referralUser->incrementData(sysConfig('referral_traffic') * MB);
+                    $referralUser->incrementData(sysConfig('referral_traffic') * MiB);
                 }
             }
 
@@ -572,7 +572,7 @@ class AuthController extends Controller
         // 账号激活后给邀请人送流量
         $inviter = $user->inviter;
         if ($inviter) {
-            $inviter->incrementData(sysConfig('referral_traffic') * MB);
+            $inviter->incrementData(sysConfig('referral_traffic') * MiB);
         }
 
         Session::flash('successMsg', trans('common.active_item', ['attribute' => trans('common.success')]));

+ 1 - 1
app/Http/Controllers/OAuthController.php

@@ -109,7 +109,7 @@ class OAuthController extends Controller
 
         if ($OauthUser) {
             if (User::whereUsername($OauthUser->getEmail())->doesntExist() && UserOauth::whereIdentifier($OauthUser->getId())->doesntExist()) { // 排除重复用户注册
-                $user = Helpers::addUser($OauthUser->getEmail(), Str::random(), MB * ((int) sysConfig('default_traffic')), null, $OauthUser->getNickname());
+                $user = Helpers::addUser($OauthUser->getEmail(), Str::random(), MiB * ((int) sysConfig('default_traffic')), null, $OauthUser->getNickname());
 
                 $user->userAuths()->create([
                     'type' => $type,

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

@@ -22,7 +22,7 @@ class AffiliateController extends Controller
         }
 
         return view('user.referral', [
-            'referral_traffic' => formatBytes(sysConfig('referral_traffic') * MB),
+            'referral_traffic' => formatBytes(sysConfig('referral_traffic'), 'MiB'),
             'referral_percent' => sysConfig('referral_percent'),
             'referral_money' => Helpers::getPriceTag(sysConfig('referral_money')),
             'totalAmount' => ReferralLog::uid()->sum('commission') / 100,

+ 2 - 2
app/Http/Controllers/UserController.php

@@ -94,7 +94,7 @@ class UserController extends Controller
             return Response::json(['status' => 'success', 'title' => trans('common.success'), 'message' => trans('user.home.attendance.done')]);
         }
 
-        $traffic = random_int((int) sysConfig('min_rand_traffic'), (int) sysConfig('max_rand_traffic')) * MB;
+        $traffic = random_int((int) sysConfig('min_rand_traffic'), (int) sysConfig('max_rand_traffic')) * MiB;
 
         if (! $user->incrementData($traffic)) {
             return Response::json(['status' => 'fail', 'title' => trans('common.failed'), 'message' => trans('user.home.attendance.failed')]);
@@ -382,7 +382,7 @@ class UserController extends Controller
         return view('user.invite', [
             'num' => auth()->user()->invite_num, // 还可以生成的邀请码数量
             'inviteList' => Invite::uid()->with(['invitee', 'inviter'])->paginate(10), // 邀请码列表
-            'referral_traffic' => formatBytes(sysConfig('referral_traffic') * MB),
+            'referral_traffic' => formatBytes(sysConfig('referral_traffic'), 'MiB'),
             'referral_percent' => sysConfig('referral_percent'),
         ]);
     }

+ 3 - 3
app/Models/Coupon.php

@@ -28,20 +28,20 @@ class Coupon extends Model
 
     public function used(): bool
     {
-        $this->attributes['status'] = 1;
+        $this->status = 1;
 
         return $this->save();
     }
 
     public function expired(): bool
     {
-        $this->attributes['status'] = 2;
+        $this->status = 2;
 
         return $this->save();
     }
 
     public function isExpired(): bool
     {
-        return $this->attributes['end_time'] < time() || $this->attributes['status'] === 2;
+        return $this->end_time < time() || $this->status === 2;
     }
 }

+ 13 - 6
app/Models/Goods.php

@@ -6,6 +6,7 @@ use App\Casts\data_rate;
 use App\Casts\money;
 use App\Utils\Helpers;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Database\Eloquent\SoftDeletes;
@@ -33,18 +34,24 @@ class Goods extends Model
         return $query->whereType($type)->whereStatus(1)->orderByDesc('sort');
     }
 
-    public function getPriceTagAttribute(): string
+    protected function priceTag(): Attribute
     {
-        return Helpers::getPriceTag($this->price);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->price),
+        );
     }
 
-    public function getRenewTagAttribute(): string
+    protected function renewTag(): Attribute
     {
-        return Helpers::getPriceTag($this->renew);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->renew),
+        );
     }
 
-    public function getTrafficLabelAttribute(): string
+    protected function trafficLabel(): Attribute
     {
-        return formatBytes($this->attributes['traffic'] * MB);
+        return Attribute::make(
+            get: fn () => formatBytes($this->traffic, 'MiB'),
+        );
     }
 }

+ 1 - 1
app/Models/Invite.php

@@ -38,7 +38,7 @@ class Invite extends Model
 
     public function getStatusLabelAttribute(): string
     {
-        return match ($this->attributes['status']) {
+        return match ($this->status) {
             0 => '<span class="badge badge-success">'.trans('common.status.unused').'</span>',
             1 => '<span class="badge badge-danger">'.trans('common.status.used').'</span>',
             2 => '<span class="badge badge-default">'.trans('common.status.expire').'</span>',

+ 10 - 7
app/Models/Marketing.php

@@ -2,6 +2,7 @@
 
 namespace App\Models;
 
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Model;
 
 /**
@@ -13,13 +14,15 @@ class Marketing extends Model
 
     protected $guarded = [];
 
-    public function getStatusLabelAttribute(): string
+    protected function statusLabel(): Attribute
     {
-        return match ($this->attributes['status']) {
-            -1 => '失败',
-            0 => '待推送',
-            1 => '成功',
-            default => '',
-        };
+        return Attribute::make(
+            get: fn () => match ($this->status) {
+                -1 => '失败',
+                0 => '待推送',
+                1 => '成功',
+                default => '',
+            },
+        );
     }
 }

+ 22 - 17
app/Models/Node.php

@@ -4,6 +4,7 @@ namespace App\Models;
 
 use App\Casts\data_rate;
 use App\Utils\IP;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -101,7 +102,7 @@ class Node extends Model
     public function users(): Collection
     {
         return User::activeUser()
-            ->where('level', '>=', $this->attributes['level'])
+            ->where('level', '>=', $this->level)
             ->where(function ($query) {
                 $query->whereIn('user_group_id', $this->userGroups->pluck('id'))->orWhereNull('user_group_id');
             })
@@ -129,34 +130,38 @@ class Node extends Model
     public function ips(int $type = 4): array
     {
         // 使用DDNS的node先通过gethostbyname获取ip地址
-        if ($this->attributes['is_ddns'] ?? 0) { // When ddns is enabled, only domain can be used to check the ip
-            $ip = gethostbyname($this->attributes['server']);
-            if (strcmp($ip, $this->attributes['server']) === 0) {
-                Log::warning('获取 【'.$this->attributes['server'].'】 IP失败'.$ip);
+        if ($this->is_ddns ?? 0) { // When ddns is enabled, only domain can be used to check the ip
+            $ip = gethostbyname($this->server);
+            if (strcmp($ip, $this->server) === 0) {
+                Log::warning('获取 【'.$this->server.'】 IP失败'.$ip);
                 $ip = '';
             }
         } else {
-            $ip = $type === 4 ? $this->attributes['ip'] : $this->attributes['ipv6']; // check the multiple existing of ip
+            $ip = $type === 4 ? $this->ip : $this->ipv6; // check the multiple existing of ip
         }
 
         return array_map('trim', explode(',', $ip));
     }
 
-    public function getTypeLabelAttribute(): string
+    protected function typeLabel(): Attribute
     {
-        return match ($this->attributes['type']) {
-            0 => 'Shadowsocks',
-            1 => 'ShadowsocksR',
-            2 => 'V2Ray',
-            3 => 'Trojan',
-            4 => 'VNet',
-            default => 'UnKnown',
-        };
+        return Attribute::make(
+            get: fn () => match ($this->type) {
+                0 => 'Shadowsocks',
+                1 => 'ShadowsocksR',
+                2 => 'V2Ray',
+                3 => 'Trojan',
+                4 => 'VNet',
+                default => 'UnKnown',
+            },
+        );
     }
 
-    public function getHostAttribute(): string
+    protected function host(): Attribute
     {
-        return $this->server ?? $this->ip ?? $this->ipv6;
+        return Attribute::make(
+            get: fn () => $this->server ?? $this->ip ?? $this->ipv6,
+        );
     }
 
     public function getSSRConfig(): array

+ 1 - 1
app/Models/NotificationLog.php

@@ -16,6 +16,6 @@ class NotificationLog extends Model
     // 通知类型
     public function getTypeLabelAttribute(): string
     {
-        return config('common.notification.labels')[$this->attributes['type']] ?? trans('common.status.unknown');
+        return config('common.notification.labels')[$this->type] ?? trans('common.status.unknown');
     }
 }

+ 5 - 5
app/Models/Order.php

@@ -126,7 +126,7 @@ class Order extends Model
 
     public function getStatusLabelAttribute(): string
     { // 订单状态
-        return $this->statusTags($this->attributes['status'], $this->attributes['is_expire']);
+        return $this->statusTags($this->status, $this->is_expire);
     }
 
     public function statusTags(int $status, bool $expire, bool $isHtml = true): string
@@ -144,7 +144,7 @@ class Order extends Model
                 $label = trans('common.order.status.review');
                 break;
             case 2:
-                if ($this->attributes['goods_id'] === null) {
+                if ($this->goods_id === null) {
                     $label = trans('common.order.status.complete');
                 } elseif ($expire) {
                     $label = trans('common.status.expire');
@@ -182,7 +182,7 @@ class Order extends Model
     // 支付渠道
     public function getPayTypeLabelAttribute(): string
     {
-        return match ($this->attributes['pay_type']) {
+        return match ($this->pay_type) {
             0 => trans('common.payment.credit'),
             1 => trans('common.payment.alipay'),
             2 => trans('common.payment.qq'),
@@ -198,12 +198,12 @@ class Order extends Model
     // 支付图标
     public function getPayTypeIconAttribute(): string
     {
-        return '/assets/images/payment/'.config('common.payment.icon')[$this->attributes['pay_type']] ?? 'coin.png';
+        return '/assets/images/payment/'.config('common.payment.icon')[$this->pay_type] ?? 'coin.png';
     }
 
     // 支付方式
     public function getPayWayLabelAttribute(): string
     {
-        return config('common.payment.labels')[$this->attributes['pay_way']] ?? '未知';
+        return config('common.payment.labels')[$this->pay_way] ?? '未知';
     }
 }

+ 14 - 10
app/Models/Payment.php

@@ -6,6 +6,7 @@ use App\Casts\money;
 use App\Utils\Helpers;
 use Auth;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
@@ -50,18 +51,21 @@ class Payment extends Model
         return $this->update(['status' => 1]);
     }
 
-    public function getAmountTagAttribute(): string
+    protected function amountTag(): Attribute
     {
-        return Helpers::getPriceTag($this->amount);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->amount),
+        );
     }
 
-    // 订单状态
-    public function getStatusLabelAttribute(): string
-    {
-        return match ($this->attributes['status']) {
-            -1 => trans('common.failed_item', ['attribute' => trans('user.pay')]),
-            1 => trans('common.success_item', ['attribute' => trans('user.pay')]),
-            default => trans('common.payment.status.wait'),
-        };
+    protected function statusLabel(): Attribute
+    { // 订单状态
+        return Attribute::make(
+            get: fn () => match ($this->status) {
+                -1 => trans('common.failed_item', ['attribute' => trans('user.pay')]),
+                1 => trans('common.success_item', ['attribute' => trans('user.pay')]),
+                default => trans('common.payment.status.wait'),
+            },
+        );
     }
 }

+ 1 - 1
app/Models/PaymentCallback.php

@@ -15,7 +15,7 @@ class PaymentCallback extends Model
 
     public function getStatusLabelAttribute(): string
     {
-        return match ($this->attributes['status']) {
+        return match ($this->status) {
             'WAIT_BUYER_PAY' => '等待买家付款',
             'WAIT_SELLER_SEND_GOODS' => '等待卖家发货',
             'TRADE_SUCCESS' => '交易成功',

+ 13 - 8
app/Models/ReferralApply.php

@@ -6,6 +6,7 @@ use App\Casts\money;
 use App\Utils\Helpers;
 use Auth;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
@@ -35,17 +36,21 @@ class ReferralApply extends Model
         return ReferralLog::whereIn('id', $this->link_logs);
     }
 
-    public function getAmountTagAttribute(): string
+    protected function amountTag(): Attribute
     {
-        return Helpers::getPriceTag($this->amount);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->amount),
+        );
     }
 
-    public function getStatusLabelAttribute(): string
+    protected function statusLabel(): Attribute
     {
-        return match ($this->attributes['status']) {
-            1 => '<span class="badge badge-sm badge-info">'.trans('common.status.pending').'</span>',
-            2 => trans('common.status.withdrawn'),
-            default => '<span class="badge badge-sm badge-warning">'.trans('common.status.applying').'</span>',
-        };
+        return Attribute::make(
+            get: fn () => match ($this->status) {
+                1 => '<span class="badge badge-sm badge-info">'.trans('common.status.pending').'</span>',
+                2 => trans('common.status.withdrawn'),
+                default => '<span class="badge badge-sm badge-warning">'.trans('common.status.applying').'</span>',
+            },
+        );
     }
 }

+ 17 - 10
app/Models/ReferralLog.php

@@ -6,6 +6,7 @@ use App\Casts\money;
 use App\Utils\Helpers;
 use Auth;
 use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Casts\Attribute;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 
@@ -40,22 +41,28 @@ class ReferralLog extends Model
         return $this->belongsTo(Order::class);
     }
 
-    public function getAmountTagAttribute(): string
+    protected function amountTag(): Attribute
     {
-        return Helpers::getPriceTag($this->amount);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->amount),
+        );
     }
 
-    public function getCommissionTagAttribute(): string
+    protected function commissionTag(): Attribute
     {
-        return Helpers::getPriceTag($this->commission);
+        return Attribute::make(
+            get: fn () => Helpers::getPriceTag($this->commission),
+        );
     }
 
-    public function getStatusLabelAttribute(): string
+    protected function statusLabel(): Attribute
     {
-        return match ($this->attributes['status']) {
-            1 => '<span class="badge badge-sm badge-info">'.trans('common.status.applying').'</span>',
-            2 => '<span class="badge badge-sm badge-default">'.trans('common.status.withdrawn').'</span>',
-            default => '<span class="badge badge-sm badge-success">'.trans('common.status.unwithdrawn').'</span>',
-        };
+        return Attribute::make(
+            get: fn () => match ($this->status) {
+                1 => '<span class="badge badge-sm badge-info">'.trans('common.status.applying').'</span>',
+                2 => '<span class="badge badge-sm badge-default">'.trans('common.status.withdrawn').'</span>',
+                default => '<span class="badge badge-sm badge-success">'.trans('common.status.unwithdrawn').'</span>',
+            },
+        );
     }
 }

+ 2 - 2
app/Models/Rule.php

@@ -23,7 +23,7 @@ class Rule extends Model
 
     public function getTypeLabelAttribute(): string
     {
-        return match ($this->attributes['type']) {
+        return match ($this->type) {
             1 => trans('admin.rule.type.reg'),
             2 => trans('admin.rule.type.domain'),
             3 => trans('admin.rule.type.ip'),
@@ -34,7 +34,7 @@ class Rule extends Model
 
     public function getTypeApiLabelAttribute(): string
     {
-        return match ($this->attributes['type']) {
+        return match ($this->type) {
             1 => 'reg',
             2 => 'domain',
             3 => 'ip',

+ 1 - 1
app/Models/RuleGroup.php

@@ -21,7 +21,7 @@ class RuleGroup extends Model
 
     public function getTypeLabelAttribute(): string
     {
-        return match ($this->attributes['type']) {
+        return match ($this->type) {
             0 => '<span class="badge badge-primary">'.trans('admin.rule.group.type.on').'</span>',
             1 => '<span class="badge badge-danger">'.trans('admin.rule.group.type.off').'</span>',
         };

+ 1 - 1
app/Models/Ticket.php

@@ -46,7 +46,7 @@ class Ticket extends Model
 
     public function getStatusLabelAttribute(): string
     {
-        return match ($this->attributes['status']) {
+        return match ($this->status) {
             0 => '<span class="badge badge-lg badge-success">'.trans('common.status.pending').'</span>',
             1 => '<span class="badge badge-lg badge-danger">'.trans('common.status.reply').'</span>',
             2 => '<span class="badge badge-lg badge-default">'.trans('common.status.closed').'</span>',

+ 4 - 4
app/Models/User.php

@@ -178,7 +178,7 @@ class User extends Authenticatable
 
     public function getLevelNameAttribute(): string
     {
-        return Level::whereLevel($this->attributes['level'])->first()->name;
+        return Level::whereLevel($this->level)->first()->name;
     }
 
     public function getCreditTagAttribute(): string
@@ -224,7 +224,7 @@ class User extends Authenticatable
 
     public function nodes(?int $userLevel = null, int $userGroupId = 0): Node|Builder
     {
-        if ($userGroupId === 0 && $this->attributes['user_group_id']) { // 使用默认的用户分组
+        if ($userGroupId === 0 && $this->user_group_id) { // 使用默认的用户分组
             $query = $this->userGroup->nodes();
         } elseif ($userGroupId) { // 使用给的用户分组
             $query = UserGroup::findOrFail($userGroupId)->nodes();
@@ -232,7 +232,7 @@ class User extends Authenticatable
             $query = Node::query();
         }
 
-        return $query->whereStatus(1)->where('level', '<=', $userLevel ?? $this->attributes['level'] ?? 0);
+        return $query->whereStatus(1)->where('level', '<=', $userLevel ?? $this->level ?? 0);
     }
 
     public function userGroup(): BelongsTo
@@ -290,7 +290,7 @@ class User extends Authenticatable
 
     public function isTrafficWarning(): bool
     { // 流量异常警告
-        return ((int) sysConfig('traffic_ban_value') * GB) <= $this->recentTrafficUsed();
+        return ((int) sysConfig('traffic_ban_value') * GiB) <= $this->recentTrafficUsed();
     }
 
     public function recentTrafficUsed()

+ 2 - 2
app/Models/UserHourlyDataFlow.php

@@ -42,13 +42,13 @@ class UserHourlyDataFlow extends Model
     public function trafficAbnormal(): array
     {
         $userTotalTrafficList = self::whereNodeId(null)
-            ->where('total', '>', MB * 50)
+            ->where('total', '>', MiB * 50)
             ->where('created_at', '>=', date('Y-m-d H:i:s', time() - 3900))
             ->groupBy('user_id')
             ->selectRaw('user_id, sum(total) as totalTraffic')->pluck('totalTraffic', 'user_id')
             ->toArray(); // 只统计50M以上的记录,加快速度
         foreach ($userTotalTrafficList as $user => $traffic) {
-            if ($traffic > (int) sysConfig('traffic_ban_value') * GB) {
+            if ($traffic > (int) sysConfig('traffic_ban_value') * GiB) {
                 $result[] = $user;
             }
         }

+ 0 - 6
app/Providers/RouteServiceProvider.php

@@ -19,8 +19,6 @@ class RouteServiceProvider extends ServiceProvider
      */
     public const HOME = '/';
 
-    protected $namespace = 'App\Http\Controllers';
-
     /**
      * Define your route model bindings, pattern filters, and other route configuration.
      */
@@ -33,19 +31,15 @@ class RouteServiceProvider extends ServiceProvider
         $this->routes(function () {
             Route::middleware('api')
                 ->prefix('api')
-                ->namespace($this->namespace)
                 ->group(base_path('routes/api.php'));
 
             Route::middleware('web')
-                ->namespace($this->namespace)
                 ->group(base_path('routes/web.php'));
 
             Route::middleware(['web', 'user'])
-                ->namespace($this->namespace)
                 ->group(base_path('routes/user.php'));
 
             Route::middleware(['web', 'admin'])
-                ->namespace($this->namespace)
                 ->group(base_path('routes/admin.php'));
         });
     }

+ 3 - 3
app/Services/OrderService.php

@@ -70,8 +70,8 @@ class OrderService
 
     private function activatePackage(): bool
     { // 激活流量包
-        if (self::$user->incrementData(self::$goods->traffic * MB)) {
-            return Helpers::addUserTrafficModifyLog($this->order->user_id, self::$user->transfer_enable - self::$goods->traffic * MB, self::$user->transfer_enable, '['.$this->order->pay_way.']加上用户购买的套餐流量', $this->order->id);
+        if (self::$user->incrementData(self::$goods->traffic * MiB)) {
+            return Helpers::addUserTrafficModifyLog($this->order->user_id, self::$user->transfer_enable - self::$goods->traffic * MiB, self::$user->transfer_enable, '['.$this->order->pay_way.']加上用户购买的套餐流量', $this->order->id);
         }
 
         return false;
@@ -130,7 +130,7 @@ class OrderService
         return [
             'u' => 0,
             'd' => 0,
-            'transfer_enable' => self::$goods->traffic * MB,
+            'transfer_enable' => self::$goods->traffic * MiB,
             'expired_at' => $expired_at,
             'reset_time' => $nextResetTime,
         ];

+ 8 - 3
app/helpers.php

@@ -1,7 +1,7 @@
 <?php
 
-const MB = 1048576;
-const GB = 1073741824;
+const MiB = 1048576;
+const GiB = 1073741824;
 
 const Minute = 60;
 const Hour = 3600;
@@ -27,7 +27,7 @@ if (! function_exists('base64url_decode')) {
 
 // 根据流量值自动转换单位输出
 if (! function_exists('formatBytes')) {
-    function formatBytes($bytes, int $precision = 2): string
+    function formatBytes(int $bytes, string $base = '', int $precision = 2): string
     {
         $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
         $bytes = max($bytes, 0);
@@ -35,6 +35,11 @@ if (! function_exists('formatBytes')) {
         $power = min($power, count($units) - 1);
         $bytes /= 1024 ** $power;
 
+        if ($base) {
+            $basePower = array_search($base, $units);
+            $power += max($basePower, 0);
+        }
+
         return round($bytes, $precision).' '.$units[$power];
     }
 }

+ 1 - 1
database/factories/UserFactory.php

@@ -29,7 +29,7 @@ class UserFactory extends Factory
             'method' => Helpers::getDefaultMethod(),
             'protocol' => Helpers::getDefaultProtocol(),
             'obfs' => Helpers::getDefaultObfs(),
-            'transfer_enable' => (int) sysConfig('default_traffic') * MB,
+            'transfer_enable' => (int) sysConfig('default_traffic') * MiB,
             'expired_at' => date('Y-m-d', strtotime(sysConfig('default_days').' days')),
             'user_group_id' => null,
         ];

+ 1 - 1
database/seeders/DatabaseSeeder.php

@@ -33,7 +33,7 @@ class DatabaseSeeder extends Seeder
         }
         if (User::doesntExist()) {
             // 生成初始管理账号
-            $user = Helpers::addUser('[email protected]', '123456', 100 * GB, sysConfig('default_days'), null, '管理员');
+            $user = Helpers::addUser('[email protected]', '123456', 100 * GiB, sysConfig('default_days'), null, '管理员');
             $user->update(['status' => 1]);
             $user->assignRole('Super Admin');
         }

+ 285 - 223
resources/views/admin/user/info.blade.php

@@ -11,7 +11,8 @@
                 @isset($user)
                     @can('admin.user.switch')
                         <div class="panel-actions">
-                            <button type="button" class="btn btn-sm btn-danger" onclick="switchToUser()">{{ trans('admin.user.info.switch') }}</button>
+                            <button type="button" class="btn btn-sm btn-danger"
+                                    onclick="switchToUser()">{{ trans('admin.user.info.switch') }}</button>
                         </div>
                     @endcan
                 @endisset
@@ -22,28 +23,34 @@
                         <div class="col-lg-6">
                             <h4 class="example-title">{{ trans('admin.user.info.account') }}</h4>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="nickname">{{ trans('model.user.nickname') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="nickname">{{ trans('model.user.nickname') }}</label>
                                 <div class="col-xl-6 col-sm-8">
                                     <input type="text" class="form-control" name="nickname" id="nickname" required/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="username">{{ trans('model.user.username') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="username">{{ trans('model.user.username') }}</label>
                                 <div class="col-xl-6 col-sm-8">
                                     <input type="text" class="form-control" name="username" id="username" required/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="password">{{ trans('model.user.password') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="password">{{ trans('model.user.password') }}</label>
                                 <div class="col-xl-6 col-sm-8">
-                                    <input type="password" class="form-control" name="password" id="password" autocomplete="new-password"
+                                    <input type="password" class="form-control" name="password" id="password"
+                                           autocomplete="new-password"
                                            placeholder="@isset($user){{ trans('common.stay_unchanged') }} @else {{ trans('common.random_generate') }} @endisset"/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="level">{{ trans('model.common.level') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="level">{{ trans('model.common.level') }}</label>
                                 <div class="col-xl-4 col-sm-8">
-                                    <select class="form-control" name="level" id="level" data-plugin="selectpicker" data-style="btn-outline btn-primary">
+                                    <select class="form-control" name="level" id="level" data-plugin="selectpicker"
+                                            data-style="btn-outline btn-primary">
                                         @foreach($levels as $level)
                                             <option value="{{$level->level}}">{{$level->name}}</option>
                                         @endforeach
@@ -51,9 +58,11 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="group">{{ trans('model.user.group') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="group">{{ trans('model.user.group') }}</label>
                                 <div class="col-xl-4 col-sm-8">
-                                    <select class="form-control" name="group" id="group" data-plugin="selectpicker" data-style="btn-outline btn-primary">
+                                    <select class="form-control" name="group" id="group" data-plugin="selectpicker"
+                                            data-style="btn-outline btn-primary">
                                         <option value="">{{ trans('common.none') }}</option>
                                         @foreach($userGroups as $group)
                                             <option value="{{$group->id}}">{{$group->name}}</option>
@@ -63,13 +72,15 @@
                             </div>
                             @isset($user)
                                 <div class="form-group row">
-                                    <label class="col-md-2 col-sm-3 col-form-label" for="credit">{{ trans('model.user.credit') }}</label>
+                                    <label class="col-md-2 col-sm-3 col-form-label"
+                                           for="credit">{{ trans('model.user.credit') }}</label>
                                     <div class="col-xl-4 col-sm-8">
                                         <div class="input-group">
                                             <p class="form-control"> {{$user->credit}} </p>
                                             @can('admin.user.updateCredit')
                                                 <div class="input-group-append">
-                                                    <button type="button" class="btn btn-danger" data-toggle="modal" data-target="#handle_user_credit">{{ trans('admin.goods.type.top_up') }}</button>
+                                                    <button type="button" class="btn btn-danger" data-toggle="modal"
+                                                            data-target="#handle_user_credit">{{ trans('admin.goods.type.top_up') }}</button>
                                                 </div>
                                             @endcan
                                         </div>
@@ -78,13 +89,16 @@
                             @endisset
 
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="invite_num">{{ trans('model.user.invite_num') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="invite_num">{{ trans('model.user.invite_num') }}</label>
                                 <div class="col-xl-4 col-sm-8">
-                                    <input type="number" class="form-control" name="invite_num" id="invite_num" value="0" required/>
+                                    <input type="number" class="form-control" name="invite_num" id="invite_num"
+                                           value="0" required/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="reset_time">{{ trans('model.user.reset_date') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="reset_time">{{ trans('model.user.reset_date') }}</label>
                                 <div class="col-xl-4 col-sm-4">
                                     <div class="input-group input-daterange" data-plugin="datepicker">
                                         <div class="input-group-prepend">
@@ -98,7 +112,8 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="expired_at">{{ trans('model.user.expired_date') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="expired_at">{{ trans('model.user.expired_date') }}</label>
                                 <div class="col-xl-4 col-sm-4">
                                     <div class="input-group input-daterange" data-plugin="datepicker">
                                         <div class="input-group-prepend">
@@ -137,9 +152,11 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="roles">{{ trans('model.user.role') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="roles">{{ trans('model.user.role') }}</label>
                                 <div class="col-xl-4 col-sm-8">
-                                    <select class="form-control show-tick" name="roles[]" id="roles" data-plugin="selectpicker" data-style="btn-outline btn-primary" multiple>
+                                    <select class="form-control show-tick" name="roles[]" id="roles"
+                                            data-plugin="selectpicker" data-style="btn-outline btn-primary" multiple>
                                         @foreach($roles as $key => $description)
                                             <option value="{{ $key }}">{{ $description }}</option>
                                         @endforeach
@@ -148,19 +165,22 @@
                             </div>
                             <hr>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="wechat">{{ trans('model.user.wechat') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="wechat">{{ trans('model.user.wechat') }}</label>
                                 <div class="col-xl-6 col-sm-8">
                                     <input type="text" class="form-control" name="wechat" id="wechat"/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="qq">{{ trans('model.user.qq') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="qq">{{ trans('model.user.qq') }}</label>
                                 <div class="col-xl-6 col-sm-8">
                                     <input type="number" class="form-control" name="qq" id="qq"/>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="remark">{{ trans('model.user.remark') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="remark">{{ trans('model.user.remark') }}</label>
                                 <div class="col-xl-6 col-sm-8">
                                     <textarea class="form-control" rows="3" name="remark" id="remark"></textarea>
                                 </div>
@@ -169,10 +189,12 @@
                         <div class="col-lg-6">
                             <h4 class="example-title">{{ trans('admin.user.info.proxy') }}</h4>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="port">{{ trans('model.user.port') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="port">{{ trans('model.user.port') }}</label>
                                 <div class="col-xl-5 col-sm-8">
                                     <div class="input-group">
-                                        <input type="number" class="form-control" name="port" id="port" placeholder="{{ trans('common.random_generate') }}"/>
+                                        <input type="number" class="form-control" name="port" id="port"
+                                               placeholder="{{ trans('common.random_generate') }}"/>
                                         <div class="input-group-append">
                                             <button class="btn btn-success" type="button" onclick="makePort()">
                                                 <i class="icon wb-refresh"></i>
@@ -182,10 +204,12 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="uuid">{{ trans('model.user.uuid') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="uuid">{{ trans('model.user.uuid') }}</label>
                                 <div class="col-xl-5 col-sm-8">
                                     <div class="input-group">
-                                        <input type="text" class="form-control" name="uuid" id="uuid" placeholder="{{ trans('common.random_generate') }}"/>
+                                        <input type="text" class="form-control" name="uuid" id="uuid"
+                                               placeholder="{{ trans('common.random_generate') }}"/>
                                         <div class="input-group-append">
                                             <button class="btn btn-success" type="button" onclick="makeUUID()">
                                                 <i class="icon wb-refresh"></i>
@@ -196,10 +220,12 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="passwd">{{ trans('model.user.proxy_passwd') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="passwd">{{ trans('model.user.proxy_passwd') }}</label>
                                 <div class="col-xl-5 col-sm-8">
                                     <div class="input-group">
-                                        <input type="text" class="form-control" name="passwd" id="passwd" placeholder="{{ trans('common.random_generate') }}"/>
+                                        <input type="text" class="form-control" name="passwd" id="passwd"
+                                               placeholder="{{ trans('common.random_generate') }}"/>
                                         <div class="input-group-append">
                                             <button class="btn btn-success" type="button" onclick="makePasswd()">
                                                 <i class="icon wb-refresh"></i>
@@ -209,20 +235,25 @@
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="method">{{ trans('model.user.proxy_method') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="method">{{ trans('model.user.proxy_method') }}</label>
                                 <div class="col-xl-5 col-sm-8">
-                                    <select class="form-control" name="method" id="method" data-plugin="selectpicker" data-style="btn-outline btn-primary">
+                                    <select class="form-control" name="method" id="method" data-plugin="selectpicker"
+                                            data-style="btn-outline btn-primary">
                                         @foreach (Helpers::methodList() as $method)
-                                            <option value="{{$method->name}}" @if($method->is_default) selected @endif>{{$method->name}}</option>
+                                            <option value="{{$method->name}}"
+                                                    @if($method->is_default) selected @endif>{{$method->name}}</option>
                                         @endforeach
                                     </select>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="transfer_enable">{{ trans('model.user.usable_traffic') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="transfer_enable">{{ trans('model.user.usable_traffic') }}</label>
                                 <div class="col-xl-5 col-sm-8">
                                     <div class="input-group">
-                                        <input type="text" class="form-control" name="transfer_enable" id="transfer_enable" value="1024" required>
+                                        <input type="text" class="form-control" name="transfer_enable"
+                                               id="transfer_enable" value="1024" required>
                                         <span class="input-group-text">GB</span>
                                     </div>
                                 </div>
@@ -248,31 +279,39 @@
                             </div>
                             <hr>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="protocol">{{ trans('model.user.proxy_protocol') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="protocol">{{ trans('model.user.proxy_protocol') }}</label>
                                 <div class="col-xl-5 col-sm-8">
-                                    <select class="form-control" name="protocol" id="protocol" data-plugin="selectpicker" data-style="btn-outline btn-primary">
+                                    <select class="form-control" name="protocol" id="protocol"
+                                            data-plugin="selectpicker" data-style="btn-outline btn-primary">
                                         @foreach (Helpers::protocolList() as $protocol)
-                                            <option value="{{$protocol->name}}" @if($protocol->is_default) selected @endif>{{$protocol->name}}</option>
+                                            <option value="{{$protocol->name}}"
+                                                    @if($protocol->is_default) selected @endif>{{$protocol->name}}</option>
                                         @endforeach
                                     </select>
                                 </div>
                             </div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="obfs">{{ trans('model.user.proxy_obfs') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="obfs">{{ trans('model.user.proxy_obfs') }}</label>
                                 <div class="col-xl-5 col-sm-8">
-                                    <select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="form-control" name="obfs" id="obfs">
+                                    <select data-plugin="selectpicker" data-style="btn-outline btn-primary"
+                                            class="form-control" name="obfs" id="obfs">
                                         @foreach (Helpers::obfsList() as $obfs)
-                                            <option value="{{$obfs->name}}" @if($obfs->is_default) selected @endif>{{$obfs->name}}</option>
+                                            <option value="{{$obfs->name}}"
+                                                    @if($obfs->is_default) selected @endif>{{$obfs->name}}</option>
                                         @endforeach
                                     </select>
                                 </div>
                             </div>
                             <hr>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="speed_limit">{{ trans('model.user.speed_limit') }}</label>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="speed_limit">{{ trans('model.user.speed_limit') }}</label>
                                 <div class="col-xl-5 col-sm-8">
                                     <div class="input-group">
-                                        <input type="number" class="form-control" name="speed_limit" id="speed_limit" value="200"/>
+                                        <input type="number" class="form-control" name="speed_limit" id="speed_limit"
+                                               value="200"/>
                                         <span class="input-group-text"> Mbps</span>
                                     </div>
                                     <span class="text-help">{{ trans('admin.zero_unlimited_hint') }} </span>
@@ -281,13 +320,15 @@
                             @isset($user)
                                 <hr>
                                 <div class="form-group row">
-                                    <label class="col-md-2 col-sm-3 col-form-label" for="inviter">{{ trans('model.user.inviter') }}</label>
+                                    <label class="col-md-2 col-sm-3 col-form-label"
+                                           for="inviter">{{ trans('model.user.inviter') }}</label>
                                     <div class="col-xl-6 col-sm-8">
                                         <p class="form-control"> {{$user->inviter->username ?? trans('common.none')}} </p>
                                     </div>
                                 </div>
                                 <div class="form-group row">
-                                    <label class="col-md-2 col-sm-3 col-form-label" for="created_at">{{ trans('model.user.created_date') }}</label>
+                                    <label class="col-md-2 col-sm-3 col-form-label"
+                                           for="created_at">{{ trans('model.user.created_date') }}</label>
                                     <div class="col-xl-6 col-sm-8">
                                         <p class="form-control"> {{$user->created_at}} </p>
                                     </div>
@@ -295,7 +336,8 @@
                             @endisset
                         </div>
                         <div class="col-12 form-actions text-right">
-                            <a href="{{route('admin.user.index')}}" class="btn btn-secondary">{{ trans('common.back') }}</a>
+                            <a href="{{route('admin.user.index')}}"
+                               class="btn btn-secondary">{{ trans('common.back') }}</a>
                             <button type="submit" class="btn btn-success">{{ trans('common.submit') }}</button>
                         </div>
                     </div>
@@ -310,7 +352,8 @@
                 <div class="modal-dialog modal-simple modal-center">
                     <div class="modal-content">
                         <div class="modal-header">
-                            <button type="button" class="close" data-dismiss="modal" aria-label="{{ trans('common.close') }}">
+                            <button type="button" class="close" data-dismiss="modal"
+                                    aria-label="{{ trans('common.close') }}">
                                 <span aria-hidden="true">×</span>
                             </button>
                             <h4 class="modal-title">{{ trans('user.recharge') }}</h4>
@@ -318,13 +361,17 @@
                         <form method="post" class="modal-body">
                             <div class="alert alert-danger" style="display: none;" id="msg"></div>
                             <div class="form-group row">
-                                <label class="col-md-2 col-sm-3 col-form-label" for="amount"> {{ trans('user.shop.change_amount') }} </label>
-                                <input type="number" class="col-sm-4 form-control" name="amount" id="amount" placeholder="{{ trans('admin.user.info.recharge_placeholder') }}" step="0.01"/>
+                                <label class="col-md-2 col-sm-3 col-form-label"
+                                       for="amount"> {{ trans('user.shop.change_amount') }} </label>
+                                <input type="number" class="col-sm-4 form-control" name="amount" id="amount"
+                                       placeholder="{{ trans('admin.user.info.recharge_placeholder') }}" step="0.01"/>
                             </div>
                         </form>
                         <div class="modal-footer">
-                            <button data-dismiss="modal" class="btn btn-danger mr-auto">{{ trans('common.close') }}</button>
-                            <button type="button" class="btn btn-primary" onclick="handleUserCredit()">{{ trans('user.recharge') }}</button>
+                            <button data-dismiss="modal"
+                                    class="btn btn-danger mr-auto">{{ trans('common.close') }}</button>
+                            <button type="button" class="btn btn-primary"
+                                    onclick="handleUserCredit()">{{ trans('user.recharge') }}</button>
                         </div>
                     </div>
                 </div>
@@ -338,194 +385,209 @@
     <script src="/assets/global/js/Plugin/bootstrap-select.js"></script>
     <script src="/assets/global/js/Plugin/bootstrap-datepicker.js"></script>
     <script>
-      $(document).ready(function() {
-          @isset($user)
-          $('#nickname').val('{{$user->nickname}}');
-        $('#username').val('{{$user->username}}');
-        $('#level').selectpicker('val', '{{$user->level}}');
-        $('#group').selectpicker('val', '{{$user->user_group_id}}');
-        $('#invite_num').val('{{$user->invite_num}}');
-        $('#reset_time').val('{{$user->reset_date}}');
-        $('#expired_at').val('{{$user->expiration_date}}');
-        $("input[name='status'][value='{{$user->status}}']").click();
-        $('#wechat').val('{{$user->wechat}}');
-        $('#qq').val('{{$user->qq}}');
-        $('#remark').val('{{$user->remark}}');
-        $('#port').val('{{$user->port}}');
-        $('#passwd').val('{{$user->passwd}}');
-        $('#method').selectpicker('val', '{{$user->method}}');
-        $('#transfer_enable').val('{{$user->transfer_enable/GB}}');
-        $("input[name='enable'][value='{{$user->enable}}']").click();
-        $('#protocol').selectpicker('val', '{{$user->protocol}}');
-        $('#obfs').selectpicker('val', '{{$user->obfs}}');
-        $('#speed_limit').val('{{$user->speed_limit}}');
-        $('#uuid').val('{{$user->vmess_id}}');
-        $('#roles').selectpicker('val', @json($user->roles()->pluck('name')));
-          @else
-          $('#level').selectpicker('val', '0');
-          @endisset
-      });
-
-      $('.input-daterange>input').datepicker({
-        format: 'yyyy-mm-dd',
-      });
-
-      @isset($user)
-      @can('admin.user.switch')
-      // 切换用户身份
-      function switchToUser() {
-        $.ajax({
-          url: '{{route('admin.user.switch', $user)}}',
-          data: {'_token': '{{csrf_token()}}'},
-          dataType: 'json',
-          method: 'POST',
-          success: function(ret) {
-            if (ret.status === 'success') {
-              swal.fire({title: ret.message, icon: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.href = '/');
-            } else {
-              swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload());
-            }
-          },
+        $(document).ready(function () {
+            @isset($user)
+            $('#nickname').val('{{$user->nickname}}');
+            $('#username').val('{{$user->username}}');
+            $('#level').selectpicker('val', '{{$user->level}}');
+            $('#group').selectpicker('val', '{{$user->user_group_id}}');
+            $('#invite_num').val('{{$user->invite_num}}');
+            $('#reset_time').val('{{$user->reset_date}}');
+            $('#expired_at').val('{{$user->expiration_date}}');
+            $("input[name='status'][value='{{$user->status}}']").click();
+            $('#wechat').val('{{$user->wechat}}');
+            $('#qq').val('{{$user->qq}}');
+            $('#remark').val('{{$user->remark}}');
+            $('#port').val('{{$user->port}}');
+            $('#passwd').val('{{$user->passwd}}');
+            $('#method').selectpicker('val', '{{$user->method}}');
+            $('#transfer_enable').val('{{$user->transfer_enable / GiB}}');
+            $("input[name='enable'][value='{{$user->enable}}']").click();
+            $('#protocol').selectpicker('val', '{{$user->protocol}}');
+            $('#obfs').selectpicker('val', '{{$user->obfs}}');
+            $('#speed_limit').val('{{$user->speed_limit}}');
+            $('#uuid').val('{{$user->vmess_id}}');
+            $('#roles').selectpicker('val', @json($user->roles()->pluck('name')));
+            @else
+            $('#level').selectpicker('val', '0');
+            @endisset
         });
-      }
-      @endcan
 
-      @can('admin.user.updateCredit')
-      // 余额充值
-      function handleUserCredit() {
-        const amount = $('#amount').val();
-        const reg = /^(-?)\d+(\.\d+)?$/; //只可以是正负数字
+        $('.input-daterange>input').datepicker({
+            format: 'yyyy-mm-dd',
+        });
 
-        if (amount.trim() === '' || amount === 0 || !reg.test(amount)) {
-          $('#msg').show().html('{{ trans('user.shop.change_amount_help') }}');
-          $('#name').focus();
-          return false;
+        @isset($user)
+        @can('admin.user.switch')
+        // 切换用户身份
+        function switchToUser() {
+            $.ajax({
+                url: '{{route('admin.user.switch', $user)}}',
+                data: {'_token': '{{csrf_token()}}'},
+                dataType: 'json',
+                method: 'POST',
+                success: function (ret) {
+                    if (ret.status === 'success') {
+                        swal.fire({
+                            title: ret.message,
+                            icon: 'success',
+                            timer: 1000,
+                            showConfirmButton: false
+                        }).then(() => window.location.href = '/');
+                    } else {
+                        swal.fire({title: ret.message, icon: 'error'}).then(() => window.location.reload());
+                    }
+                },
+            });
         }
+        @endcan
 
-        $.ajax({
-          url: '{{route('admin.user.updateCredit', $user)}}',
-          method: 'POST',
-          data: {_token: '{{csrf_token()}}', amount: amount},
-          beforeSend: function() {
-            $('#msg').show().html('{{ trans('user.recharging') }}');
-          },
-          success: function(ret) {
-            if (ret.status === 'fail') {
-              $('#msg').show().html(ret.message);
-              return false;
-            } else {
-              $('#handle_user_credit').modal('hide');
-              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());
-              }
+        @can('admin.user.updateCredit')
+        // 余额充值
+        function handleUserCredit() {
+            const amount = $('#amount').val();
+            const reg = /^(-?)\d+(\.\d+)?$/; //只可以是正负数字
+
+            if (amount.trim() === '' || amount === 0 || !reg.test(amount)) {
+                $('#msg').show().html('{{ trans('user.shop.change_amount_help') }}');
+                $('#name').focus();
+                return false;
             }
-          },
-          error: function() {
-            $('#msg').show().html('{{ trans('common.request_failed') }}');
-          },
-          complete: function() {
-          },
-        });
-      }
-      @endcan
-      @endisset
 
-      // ajax同步提交
-      function Submit() {
-        // 用途
-        let usage = '';
-        $.each($('input:checkbox[name=\'usage\']'), function() {
-          if (this.checked) {
-            usage += $(this).val() + ',';
-          }
-        });
+            $.ajax({
+                url: '{{route('admin.user.updateCredit', $user)}}',
+                method: 'POST',
+                data: {_token: '{{csrf_token()}}', amount: amount},
+                beforeSend: function () {
+                    $('#msg').show().html('{{ trans('user.recharging') }}');
+                },
+                success: function (ret) {
+                    if (ret.status === 'fail') {
+                        $('#msg').show().html(ret.message);
+                        return false;
+                    } else {
+                        $('#handle_user_credit').modal('hide');
+                        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 () {
+                    $('#msg').show().html('{{ trans('common.request_failed') }}');
+                },
+                complete: function () {
+                },
+            });
+        }
+        @endcan
+        @endisset
 
-        $.ajax({
-          method: @isset($user)'PUT' @else 'POST' @endisset,
-          url: '{{isset($user)? route('admin.user.update', $user) : route('admin.user.store')}}',
-          dataType: 'json',
-          data: {
-            _token: '{{csrf_token()}}',
-            nickname: $('#nickname').val(),
-            username: $('#username').val(),
-            password: $('#password').val(),
-            port: $('#port').val(),
-            passwd: $('#passwd').val(),
-            uuid: $('#uuid').val(),
-            transfer_enable: $('#transfer_enable').val(),
-            enable: $('input:radio[name=\'enable\']:checked').val(),
-            method: $('#method option:selected').val(),
-            protocol: $('#protocol option:selected').val(),
-            obfs: $('#obfs option:selected').val(),
-            speed_limit: $('#speed_limit').val(),
-            wechat: $('#wechat').val(),
-            qq: $('#qq').val(),
-            expired_at: $('#expired_at').val(),
-            remark: $('#remark').val(),
-            level: $('#level').val(),
-            user_group_id: $('#group').val(),
-            roles: $('#roles').val(),
-            reset_time: $('#reset_time').val(),
-            invite_num: $('#invite_num').val(),
-            status: $('input:radio[name=\'status\']:checked').val(),
-          },
-          success: function(ret) {
-            if (ret.status === 'success') {
-              swal.fire({
-                title: '{{ trans('admin.hint') }}',
-                text: '{{ trans('admin.user.update_help') }}',
-                icon: 'question',
-                showCancelButton: true,
-                cancelButtonText: '{{ trans('common.close') }}',
-                confirmButtonText: '{{ trans('common.confirm') }}',
-              }).then((result) => {
-                    if (result.value) {
-                      window.location.href = '{!! route('admin.user.index').(Request::getQueryString()?('?'.Request::getQueryString()):'') !!}';
+        // ajax同步提交
+        function Submit() {
+            // 用途
+            let usage = '';
+            $.each($('input:checkbox[name=\'usage\']'), function () {
+                if (this.checked) {
+                    usage += $(this).val() + ',';
+                }
+            });
+
+            $.ajax({
+                method: @isset($user)'PUT' @else 'POST' @endisset,
+                url: '{{isset($user)? route('admin.user.update', $user) : route('admin.user.store')}}',
+                dataType: 'json',
+                data: {
+                    _token: '{{csrf_token()}}',
+                    nickname: $('#nickname').val(),
+                    username: $('#username').val(),
+                    password: $('#password').val(),
+                    port: $('#port').val(),
+                    passwd: $('#passwd').val(),
+                    uuid: $('#uuid').val(),
+                    transfer_enable: $('#transfer_enable').val(),
+                    enable: $('input:radio[name=\'enable\']:checked').val(),
+                    method: $('#method option:selected').val(),
+                    protocol: $('#protocol option:selected').val(),
+                    obfs: $('#obfs option:selected').val(),
+                    speed_limit: $('#speed_limit').val(),
+                    wechat: $('#wechat').val(),
+                    qq: $('#qq').val(),
+                    expired_at: $('#expired_at').val(),
+                    remark: $('#remark').val(),
+                    level: $('#level').val(),
+                    user_group_id: $('#group').val(),
+                    roles: $('#roles').val(),
+                    reset_time: $('#reset_time').val(),
+                    invite_num: $('#invite_num').val(),
+                    status: $('input:radio[name=\'status\']:checked').val(),
+                },
+                success: function (ret) {
+                    if (ret.status === 'success') {
+                        swal.fire({
+                            title: '{{ trans('admin.hint') }}',
+                            text: '{{ trans('admin.user.update_help') }}',
+                            icon: 'question',
+                            showCancelButton: true,
+                            cancelButtonText: '{{ trans('common.close') }}',
+                            confirmButtonText: '{{ trans('common.confirm') }}',
+                        }).then((result) => {
+                                if (result.value) {
+                                    window.location.href = '{!! route('admin.user.index').(Request::getQueryString()?('?'.Request::getQueryString()):'') !!}';
+                                }
+                            },
+                        );
+                    } else {
+                        swal.fire({title: ret.message, icon: 'error', timer: 1000, showConfirmButton: false});
                     }
-                  },
-              );
-            } else {
-              swal.fire({title: ret.message, icon: 'error', timer: 1000, showConfirmButton: false});
-            }
-          },
-          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: '{{ trans('admin.hint') }}', html: str, icon: 'error', confirmButtonText: '{{ trans('common.confirm') }}'});
-            }
-          },
-        });
+                },
+                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: '{{ trans('admin.hint') }}',
+                            html: str,
+                            icon: 'error',
+                            confirmButtonText: '{{ trans('common.confirm') }}'
+                        });
+                    }
+                },
+            });
 
-        return false;
-      }
+            return false;
+        }
 
-      // 生成随机端口
-      function makePort() {
-        $.get('{{route('getPort')}}', function(ret) {
-          $('#port').val(ret);
-        });
-      }
+        // 生成随机端口
+        function makePort() {
+            $.get('{{route('getPort')}}', function (ret) {
+                $('#port').val(ret);
+            });
+        }
 
-      // 生成UUID
-      function makeUUID() {
-        $.get('{{route('createUUID')}}', function(ret) {
-          $('#uuid').val(ret);
-        });
-      }
+        // 生成UUID
+        function makeUUID() {
+            $.get('{{route('createUUID')}}', function (ret) {
+                $('#uuid').val(ret);
+            });
+        }
 
-      // 生成随机密码
-      function makePasswd() {
-        $.get('{{route('createStr')}}', function(ret) {
-          $('#passwd').val(ret);
-        });
-      }
+        // 生成随机密码
+        function makePasswd() {
+            $.get('{{route('createStr')}}', function (ret) {
+                $('#passwd').val(ret);
+            });
+        }
     </script>
 @endsection