优化管理首页
This commit is contained in:
@@ -13,18 +13,37 @@ namespace App\Http\Controllers\Admin;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Room;
|
use App\Models\Room;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Services\ChatStateService;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类功能:负责后台首页仪表盘的汇总统计展示。
|
||||||
|
*/
|
||||||
class DashboardController extends Controller
|
class DashboardController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 注入聊天室状态服务,供仪表盘读取实时在线数据。
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly ChatStateService $chatState,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示后台首页与全局统计
|
* 显示后台首页与全局统计
|
||||||
*/
|
*/
|
||||||
public function index(): View
|
public function index(): View
|
||||||
{
|
{
|
||||||
|
$onlineUsernames = collect();
|
||||||
|
|
||||||
|
foreach ($this->chatState->getAllActiveRoomIds() as $roomId) {
|
||||||
|
// 使用在线名单服务的懒清理结果,保证统计口径与聊天室在线列表一致。
|
||||||
|
$onlineUsernames = $onlineUsernames->merge(array_keys($this->chatState->getRoomUsers($roomId)));
|
||||||
|
}
|
||||||
|
|
||||||
$stats = [
|
$stats = [
|
||||||
'total_users' => User::count(),
|
'total_users' => User::count(),
|
||||||
'total_rooms' => Room::count(),
|
'total_rooms' => Room::count(),
|
||||||
|
'online_users' => $onlineUsernames->unique()->count(),
|
||||||
// 更多统计指标以后再发掘
|
// 更多统计指标以后再发掘
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
<h3 class="text-gray-500 text-sm font-medium mb-1">总计聊天频道数</h3>
|
<h3 class="text-gray-500 text-sm font-medium mb-1">总计聊天频道数</h3>
|
||||||
<p class="text-3xl font-bold text-gray-800">{{ $stats['total_rooms'] }}</p>
|
<p class="text-3xl font-bold text-gray-800">{{ $stats['total_rooms'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white rounded-xl shadow-sm p-6 border border-gray-100">
|
||||||
|
<h3 class="text-gray-500 text-sm font-medium mb-1">当前在线人数</h3>
|
||||||
|
<p class="text-3xl font-bold text-emerald-600">{{ $stats['online_users'] }}</p>
|
||||||
|
<p class="mt-2 text-xs text-gray-400">按 Redis 在线心跳实时去重统计</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件功能:后台仪表盘统计功能测试
|
||||||
|
*
|
||||||
|
* 覆盖后台首页在线人数卡片展示,确保仪表盘统计口径与聊天室在线名单一致。
|
||||||
|
*
|
||||||
|
* @author ChatRoom Laravel
|
||||||
|
*
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Tests\Feature\Feature;
|
||||||
|
|
||||||
|
use App\Models\Room;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类功能:验证后台仪表盘核心统计数据的展示。
|
||||||
|
*/
|
||||||
|
class AdminDashboardControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个测试前清空 Redis,避免在线名单缓存影响断言结果。
|
||||||
|
*/
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
Redis::flushall();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证后台仪表盘会显示去重后的在线人数。
|
||||||
|
*/
|
||||||
|
public function test_dashboard_displays_unique_online_user_count(): void
|
||||||
|
{
|
||||||
|
$siteOwner = User::factory()->create([
|
||||||
|
'id' => 1,
|
||||||
|
'username' => 'site-owner',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$roomOne = Room::create(['room_name' => '后台房间一']);
|
||||||
|
$roomTwo = Room::create(['room_name' => '后台房间二']);
|
||||||
|
|
||||||
|
// 同一用户重复出现在多个房间时,仪表盘应按全局去重后的在线人数展示。
|
||||||
|
Redis::hset("room:{$roomOne->id}:users", 'alice', json_encode(['username' => 'alice'], JSON_UNESCAPED_UNICODE));
|
||||||
|
Redis::setex("room:{$roomOne->id}:alive:alice", 90, 1);
|
||||||
|
Redis::hset("room:{$roomTwo->id}:users", 'alice', json_encode(['username' => 'alice'], JSON_UNESCAPED_UNICODE));
|
||||||
|
Redis::setex("room:{$roomTwo->id}:alive:alice", 90, 1);
|
||||||
|
Redis::hset("room:{$roomTwo->id}:users", 'bob', json_encode(['username' => 'bob'], JSON_UNESCAPED_UNICODE));
|
||||||
|
Redis::setex("room:{$roomTwo->id}:alive:bob", 90, 1);
|
||||||
|
|
||||||
|
$response = $this->actingAs($siteOwner)->get(route('admin.dashboard'));
|
||||||
|
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertSee('当前在线人数');
|
||||||
|
$response->assertSee('2');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user