Files
UserOnlineStatus/plugins/UserOnlineDevices/Controllers/UserOnlineDevicesController.php
CN-JS-HuiBai 38666db71a 修复错误
2026-04-07 18:13:12 +08:00

148 lines
5.1 KiB
PHP

<?php
namespace Plugin\UserOnlineDevices\Controllers;
use App\Http\Controllers\PluginController;
use App\Models\User;
use App\Services\DeviceStateService;
use DateTimeInterface;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
class UserOnlineDevicesController extends PluginController
{
public function __construct(
private readonly DeviceStateService $deviceStateService
) {
}
public function index(Request $request): View
{
$securePath = admin_setting('secure_path', admin_setting('frontend_admin_path', hash('crc32b', config('app.key'))));
return view('UserOnlineDevices::admin-index', [
'apiEndpoint' => url('/api/v2/' . $securePath . '/user-online-devices/users'),
'adminHomeUrl' => url('/' . $securePath),
'defaultPageSize' => (int) $this->getConfig('default_page_size', 20),
]);
}
public function users(Request $request)
{
if ($error = $this->beforePluginAction()) {
return $this->fail($error);
}
$defaultPageSize = (int) $this->getConfig('default_page_size', 20);
$pageSize = (int) $request->integer('per_page', $defaultPageSize);
$pageSize = in_array($pageSize, [20, 50, 100], true) ? $pageSize : $defaultPageSize;
$keyword = trim((string) $request->query('keyword', ''));
$query = User::query()
->select([
'id',
'email',
'plan_id',
'online_count',
'last_online_at',
'created_at',
])
->with(['plan:id,name'])
->orderByDesc('id');
if ($keyword !== '') {
$query->where(function ($builder) use ($keyword) {
$builder->where('email', 'like', '%' . $keyword . '%');
if (ctype_digit($keyword)) {
$builder->orWhere('id', (int) $keyword);
}
});
}
/** @var LengthAwarePaginator $paginator */
$paginator = $query->paginate($pageSize)->appends($request->query());
$userIds = $paginator->getCollection()->pluck('id')->all();
$devicesByUser = $this->deviceStateService->getUsersDevices($userIds);
$paginator->setCollection(
$paginator->getCollection()->map(function (User $user) use ($devicesByUser) {
$ips = array_values($devicesByUser[$user->id] ?? []);
sort($ips);
$user->online_devices = $ips;
$user->online_count_live = count($ips);
$user->subscription_name = $user->plan?->name ?: 'No subscription';
$user->last_online_text = $this->formatDateTime($user->last_online_at);
$user->created_text = $this->formatDateTime($user->created_at);
return $user;
})
);
$pageUsers = $paginator->getCollection()->count();
$usersWithOnlineIp = $paginator->getCollection()->filter(function (User $user) {
return ($user->online_count_live ?? 0) > 0;
})->count();
$totalOnlineIps = $paginator->getCollection()->sum(function (User $user) {
return (int) ($user->online_count_live ?? 0);
});
return $this->success([
'list' => $paginator->getCollection()->map(function (User $user) {
return [
'id' => $user->id,
'email' => $user->email,
'subscription_name' => $user->subscription_name,
'online_count' => (int) ($user->online_count_live ?? 0),
'online_devices' => $user->online_devices ?? [],
'last_online_text' => $user->last_online_text ?? '-',
'created_text' => $user->created_text ?? '-',
];
})->values()->all(),
'filters' => [
'keyword' => $keyword,
'per_page' => $pageSize,
],
'summary' => [
'page_users' => $pageUsers,
'users_with_online_ip' => $usersWithOnlineIp,
'total_online_ips' => $totalOnlineIps,
'current_page' => $paginator->currentPage(),
],
'pagination' => [
'current' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
'per_page' => $paginator->perPage(),
'total' => $paginator->total(),
],
]);
}
private function formatDateTime(mixed $value): string
{
if ($value instanceof DateTimeInterface) {
return $value->format('Y-m-d H:i:s');
}
if (is_numeric($value)) {
$timestamp = (int) $value;
if ($timestamp > 0) {
return date('Y-m-d H:i:s', $timestamp);
}
}
if (is_string($value) && trim($value) !== '') {
$timestamp = strtotime($value);
if ($timestamp !== false) {
return date('Y-m-d H:i:s', $timestamp);
}
}
return '-';
}
}