diff --git a/app/Http/Controllers/DutyHallController.php b/app/Http/Controllers/DutyHallController.php index caf6e60..910fa71 100644 --- a/app/Http/Controllers/DutyHallController.php +++ b/app/Http/Controllers/DutyHallController.php @@ -5,14 +5,20 @@ * 左侧五个子菜单:任职列表、日榜、周榜、月榜、总榜 * 路由:GET /duty-hall?tab=roster|day|week|month|all * + * 榜单统计三项指标: + * 1. 在线时长 — position_duty_logs.duration_seconds 合计 + * 2. 管理操作次数 — position_authority_logs 非任免类操作次数(warn/kick/mute/banip/other) + * 3. 奖励金币次数 — position_authority_logs WHERE action_type='reward' 的次数及累计金额 + * * @author ChatRoom Laravel * - * @version 1.1.0 + * @version 1.2.0 */ namespace App\Http\Controllers; use App\Models\Department; +use App\Models\PositionAuthorityLog; use App\Models\PositionDutyLog; use Illuminate\Http\Request; use Illuminate\View\View; @@ -26,7 +32,7 @@ class DutyHallController extends Controller { $tab = $request->input('tab', 'roster'); - // ── 任职列表:按部门→职务展示全部(含空缺) ──────────────────── + // ── 任职列表:按部门→职务展示全部(含空缺) ────────────────── $currentStaff = null; if ($tab === 'roster') { $currentStaff = Department::query() @@ -38,26 +44,64 @@ class DutyHallController extends Controller ->get(); } - // ── 日/周/月/总榜:勤务时长排行 ────────────────────────────────── + // ── 日/周/月/总榜:三项指标综合排行 ───────────────────────── $leaderboard = null; if (in_array($tab, ['day', 'week', 'month', 'all'])) { - $query = PositionDutyLog::query() + + // ① 在线时长(position_duty_logs) + $dutyQuery = PositionDutyLog::query() ->selectRaw('user_id, SUM(duration_seconds) as total_seconds, COUNT(*) as checkin_count'); - // 按时间段过滤 + // ② 管理操作(position_authority_logs,排除任命/撤销等人事操作) + $authQuery = PositionAuthorityLog::query() + ->selectRaw(' + user_id, + COUNT(*) as admin_count, + SUM(CASE WHEN action_type = \'reward\' THEN 1 ELSE 0 END) as reward_count, + SUM(CASE WHEN action_type = \'reward\' THEN COALESCE(amount, 0) ELSE 0 END) as reward_total + ') + ->whereNotIn('action_type', ['appoint', 'revoke']); + + // 按时间段同步过滤两张表 match ($tab) { - 'day' => $query->whereDate('login_at', today()), - 'week' => $query->whereBetween('login_at', [now()->startOfWeek(), now()->endOfWeek()]), - 'month' => $query->whereYear('login_at', now()->year)->whereMonth('login_at', now()->month), - 'all' => null, // 不加时间限制 + 'day' => [ + $dutyQuery->whereDate('login_at', today()), + $authQuery->whereDate('created_at', today()), + ], + 'week' => [ + $dutyQuery->whereBetween('login_at', [now()->startOfWeek(), now()->endOfWeek()]), + $authQuery->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()]), + ], + 'month' => [ + $dutyQuery->whereYear('login_at', now()->year)->whereMonth('login_at', now()->month), + $authQuery->whereYear('created_at', now()->year)->whereMonth('created_at', now()->month), + ], + 'all' => null, // 不限制时间 }; - $leaderboard = $query + // 执行查询 + $dutyRows = $dutyQuery ->groupBy('user_id') ->orderByDesc('total_seconds') ->limit(20) ->with('user') ->get(); + + // 管理操作数据(按 user_id 索引,方便后续合并) + $authMap = $authQuery + ->groupBy('user_id') + ->get() + ->keyBy('user_id'); + + // 合并两表数据:为每条勤务记录附加管理操作指标 + $leaderboard = $dutyRows->map(function ($row) use ($authMap) { + $auth = $authMap->get($row->user_id); + $row->admin_count = (int) ($auth?->admin_count ?? 0); + $row->reward_count = (int) ($auth?->reward_count ?? 0); + $row->reward_total = (int) ($auth?->reward_total ?? 0); + + return $row; + }); } // 各榜标签配置 diff --git a/resources/views/duty-hall/index.blade.php b/resources/views/duty-hall/index.blade.php index fcb88f6..e486c8d 100644 --- a/resources/views/duty-hall/index.blade.php +++ b/resources/views/duty-hall/index.blade.php @@ -154,7 +154,7 @@

{{ $tabMeta['icon'] }} 勤务{{ $tabMeta['label'] }}

-

{{ $periodLabel }} · 按在职期间登录时长排名

+

{{ $periodLabel }} · 综合统计在线时长、管理操作、奖励金币

@@ -164,13 +164,15 @@

该时段暂无勤务记录

@else - {{-- 表头 --}} + {{-- 表头(桌面端网格:名次1 + 成员4 + 在线3 + 签到2 + 管理操作2) --}}
+ class="hidden md:grid grid-cols-12 gap-2 px-5 py-2.5 bg-gray-50 border-b border-gray-100 text-xs font-bold text-gray-400 uppercase tracking-wide">
名次
-
成员
-
在线时长
-
签到次数
+
成员
+
🕐 在线时长
+
📋 登录
+
⚡管理
+
🎁奖励
@foreach ($leaderboard as $i => $row) @@ -183,41 +185,115 @@ 2 => '🥉', default => null, }; + $rowBg = match ($i) { + 0 => 'bg-yellow-50/50', + 1 => 'bg-gray-50/70', + 2 => 'bg-amber-50/40', + default => '', + }; @endphp + + {{-- 桌面端行 --}}
+ class="hidden md:grid grid-cols-12 gap-2 items-center px-5 py-3.5 + border-b border-gray-50 last:border-0 {{ $rowBg }} + hover:bg-purple-50/30 transition-colors"> + {{-- 名次 --}}
@if ($medal) - {{ $medal }} + {{ $medal }} @else {{ $i + 1 }} @endif
+ {{-- 成员 --}} -
+

{{ $row->user?->username ?? '未知' }}

-

LV.{{ $row->user?->user_level ?? '' }}

+

LV.{{ $row->user?->user_level ?? '' }}

- {{-- 时长 --}} + + {{-- 在线时长 --}}
{{ $h }}h {{ $m }}m
- {{-- 次数 --}} -
+ + {{-- 登录次数 --}} +
{{ $row->checkin_count }} 次
+ + {{-- 管理操作次数 --}} +
+ @if ($row->admin_count > 0) + + {{ $row->admin_count }} + + @else + + @endif +
+ + {{-- 奖励金币次数 --}} +
+ @if ($row->reward_count > 0) + + {{ $row->reward_count }} + + @else + + @endif +
+
+ + {{-- 移动端:紧凑卡片 --}} +
+
+ @if ($medal) + {{ $medal }} + @else + {{ $i + 1 }} + @endif +
+ +
+

{{ $row->user?->username ?? '未知' }} +

+

{{ $h }}h{{ $m }}m · + 登录{{ $row->checkin_count }}次

+
+
+ @if ($row->admin_count > 0) +

⚡{{ $row->admin_count }}次管理

+ @endif + @if ($row->reward_count > 0) +

🎁{{ $row->reward_count }}次奖励

+ @endif +
@endforeach + + {{-- 图例说明 --}} +
+ 🕐 在线时长:在职期间进入房间的累计时长 + 📋 登录:进入房间次数 + ⚡ 管理:警告/踢出/禁言/封IP等操作次数 + 🎁 奖励:发送奖励金币次数(悬停查看总金额) +
@endif
@endif