Files
chatroom/app/Http/Controllers/DutyHallController.php
lkddi 476499832f 功能:勤务台榜单新增管理操作次数 + 奖励金币次数统计
DutyHallController:
- 新增 position_authority_logs 关联查询
- 统计管理操作次数(warn/kick/mute/banip/other,排除人事任免)
- 统计奖励金币次数及累计金额(action_type=reward)
- 时间范围统一过滤(日/周/月/总)
- 合并两表数据到榜单 Collection

duty-hall/index.blade.php:
- 表格扩展为 6 列:名次、成员、在线时长、登录次数、管理操作、奖励金币
- 奖励金币栏 hover 显示次数+总金额 tooltip
- 移动端显示紧凑卡片(管理/奖励只在 >0 时显示)
- 底部图例说明各列含义
2026-03-01 10:51:48 +08:00

124 lines
4.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:勤务台页面控制器
* 左侧五个子菜单:任职列表、日榜、周榜、月榜、总榜
* 路由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.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;
class DutyHallController extends Controller
{
/**
* 勤务台主页(根据 tab 切换内容)
*/
public function index(Request $request): View
{
$tab = $request->input('tab', 'roster');
// ── 任职列表:按部门→职务展示全部(含空缺) ──────────────────
$currentStaff = null;
if ($tab === 'roster') {
$currentStaff = Department::query()
->with([
'positions' => fn ($q) => $q->orderByDesc('rank'),
'positions.activeUserPositions.user',
])
->orderByDesc('rank')
->get();
}
// ── 日/周/月/总榜:三项指标综合排行 ─────────────────────────
$leaderboard = null;
if (in_array($tab, ['day', 'week', 'month', 'all'])) {
// ① 在线时长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' => [
$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, // 不限制时间
};
// 执行查询
$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;
});
}
// 各榜标签配置
$tabs = [
'roster' => ['label' => '任职列表', 'icon' => '🏛️'],
'day' => ['label' => '日榜', 'icon' => '☀️'],
'week' => ['label' => '周榜', 'icon' => '📆'],
'month' => ['label' => '月榜', 'icon' => '🗓️'],
'all' => ['label' => '总榜', 'icon' => '🏆'],
];
return view('duty-hall.index', compact(
'tab',
'tabs',
'currentStaff',
'leaderboard',
));
}
}