From ec66dca3581c5a2c7025482d8661fe83216d60ab Mon Sep 17 00:00:00 2001 From: xiaomlove <1939737565@qq.com> Date: Tue, 21 Oct 2025 03:22:55 +0700 Subject: [PATCH] IP Search --- app/Filament/Pages/IpSearch.php | 159 ++++++++++++++++++ app/Policies/IpLogPolicy.php | 76 +++++++++ resources/lang/en/ip-search.php | 12 ++ resources/lang/zh_CN/ip-search.php | 12 ++ resources/lang/zh_TW/ip-search.php | 12 ++ .../views/filament/pages/ip-search.blade.php | 3 + 6 files changed, 274 insertions(+) create mode 100644 app/Filament/Pages/IpSearch.php create mode 100644 app/Policies/IpLogPolicy.php create mode 100644 resources/lang/en/ip-search.php create mode 100644 resources/lang/zh_CN/ip-search.php create mode 100644 resources/lang/zh_TW/ip-search.php create mode 100644 resources/views/filament/pages/ip-search.blade.php diff --git a/app/Filament/Pages/IpSearch.php b/app/Filament/Pages/IpSearch.php new file mode 100644 index 00000000..4d4b2d12 --- /dev/null +++ b/app/Filament/Pages/IpSearch.php @@ -0,0 +1,159 @@ +records(fn (array $filters, int $page, int $recordsPerPage): LengthAwarePaginator => self::getRecords($filters, $page, $recordsPerPage)) + ->columns([ + TextColumn::make('userid') + ->label(__('label.username')) + ->state(fn (array $record) => username_for_admin($record['userid'])) + , + TextColumn::make('last_access_ip') + ->label(__('ip-search.last_access_ip')) + , + TextColumn::make('last_access') + ->label(__('ip-search.last_access')) + , + TextColumn::make('ip_count') + ->label(__('ip-search.ip_count')) + ->state(function (array $record) { + return new HtmlString(sprintf( + '%s', + IpLogResource::getUrl('index', ['filters[uid][uid]' => $record['userid']]), $record['ip_count'] + )); + }) + , + TextColumn::make('ip_last_access') + ->label(__('ip-search.ip_last_access')) + , + TextColumn::make('user_added') + ->label(__('ip-search.user_added')) + , + TextColumn::make('invited_by') + ->state(fn (array $record) => $record['invited_by'] > 0 ? username_for_admin($record['invited_by']) : '') + ->label(__('ip-search.invited_by')) + , + ]) + ->filters([ + Filter::make('ip') + ->schema([ + TextInput::make('ip') + ->label(__('ip-search.label')) + ->placeholder(__('ip-search.placeholder')) + , + ]) + ]) + ->recordActions([ +// ViewAction::make(), +// EditAction::make(), +// DeleteAction::make(), + ]) +// ->toolbarActions([ +// BulkActionGroup::make([ +//// DeleteBulkAction::make(), +// ]), +// ]); + ; + } + + private static function getRecords(array $filters, int $page, int $recordsPerPage): LengthAwarePaginator + { + $total = 0; + $results = []; + if (!empty($filters['ip']['ip'])) { + $query = DB::table('iplog') + ->leftJoin('users', 'users.id', '=', 'iplog.userid') + ->select([ + 'iplog.userid', + 'users.username', + 'users.last_access', + DB::raw('users.added as user_added'), + 'users.invited_by', + 'users.ip AS last_access_ip', + DB::raw('MAX(iplog.access) AS ip_last_access'), + DB::raw('0 AS ip_count'), + ]) + ->whereRaw("iplog.ip = '{$filters['ip']['ip']}'") + ; + $total = $query->clone()->distinct()->count('iplog.userid'); + $records = $query->groupBy('iplog.userid') + ->orderByDesc('ip_last_access') + ->forPage($page, $recordsPerPage) + ->get() + ; + + if ($records->isNotEmpty()) { + $userIdArr = $records->pluck('userid')->toArray(); + $ipCountResult = IpLog::query() + ->whereIn('userid', $userIdArr) + ->selectRaw('userid, COUNT(distinct ip) AS count') + ->groupBy('userid') + ->get() + ->pluck('count', 'userid') + ->toArray(); + ; + foreach ($records as $record) { + $item = json_decode(json_encode($record), true); + $item['ip_count'] = $ipCountResult[$item['userid']] ?? 0; + $results[] = $item; + } + } + } + return new LengthAwarePaginator( + $results, + total: $total, + perPage: $recordsPerPage, + currentPage: $page, + ); + } +} diff --git a/app/Policies/IpLogPolicy.php b/app/Policies/IpLogPolicy.php new file mode 100644 index 00000000..1deac624 --- /dev/null +++ b/app/Policies/IpLogPolicy.php @@ -0,0 +1,76 @@ +can($user); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, IpLog $ipLog): bool + { + return $this->can($user); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return false; + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, IpLog $ipLog): bool + { + return false; + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, IpLog $ipLog): bool + { + return $this->can($user); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, IpLog $ipLog): bool + { + return false; + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, IpLog $ipLog): bool + { + return $this->can($user); + } + + private function can(User $user) + { + if ($user->class >= User::CLASS_SYSOP) { + return true; + } + return false; + } +} diff --git a/resources/lang/en/ip-search.php b/resources/lang/en/ip-search.php new file mode 100644 index 00000000..81d6e962 --- /dev/null +++ b/resources/lang/en/ip-search.php @@ -0,0 +1,12 @@ + 'IP Search', + 'placeholder' => 'Enter the IP to search; otherwise results will be empty', + 'last_access_ip' => 'Latest IP', + 'last_access' => 'Last access', + 'ip_count' => 'IP count', + 'ip_last_access' => 'This IP last accessed', + 'user_added' => 'Join time', + 'invited_by' => 'Invited by', +]; diff --git a/resources/lang/zh_CN/ip-search.php b/resources/lang/zh_CN/ip-search.php new file mode 100644 index 00000000..d48033a9 --- /dev/null +++ b/resources/lang/zh_CN/ip-search.php @@ -0,0 +1,12 @@ + 'IP 搜索', + 'placeholder' => '输入要搜索的 IP,否则结果为空', + 'last_access_ip' => '最近 IP', + 'last_access' => '最近访问', + 'ip_count' => 'IP 数', + 'ip_last_access' => '此 IP 最近访问', + 'user_added' => '加入时间', + 'invited_by' => '邀请者', +]; diff --git a/resources/lang/zh_TW/ip-search.php b/resources/lang/zh_TW/ip-search.php new file mode 100644 index 00000000..5a415641 --- /dev/null +++ b/resources/lang/zh_TW/ip-search.php @@ -0,0 +1,12 @@ + 'IP 搜索', + 'placeholder' => '輸入要搜索的 IP,否則結果爲空', + 'last_access_ip' => '最近 IP', + 'last_access' => '最近訪問', + 'ip_count' => 'IP 數', + 'ip_last_access' => '此 IP 最近訪問', + 'user_added' => '加入時間', + 'invited_by' => '邀請者', +]; diff --git a/resources/views/filament/pages/ip-search.blade.php b/resources/views/filament/pages/ip-search.blade.php new file mode 100644 index 00000000..ce096a2d --- /dev/null +++ b/resources/views/filament/pages/ip-search.blade.php @@ -0,0 +1,3 @@ + + {{ $this->table }} +