功能:勤务台榜单新增管理操作次数 + 奖励金币次数统计

DutyHallController:
- 新增 position_authority_logs 关联查询
- 统计管理操作次数(warn/kick/mute/banip/other,排除人事任免)
- 统计奖励金币次数及累计金额(action_type=reward)
- 时间范围统一过滤(日/周/月/总)
- 合并两表数据到榜单 Collection

duty-hall/index.blade.php:
- 表格扩展为 6 列:名次、成员、在线时长、登录次数、管理操作、奖励金币
- 奖励金币栏 hover 显示次数+总金额 tooltip
- 移动端显示紧凑卡片(管理/奖励只在 >0 时显示)
- 底部图例说明各列含义
This commit is contained in:
2026-03-01 10:51:48 +08:00
parent 5a7d1565e5
commit 476499832f
2 changed files with 145 additions and 25 deletions

View File

@@ -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;
});
}
// 各榜标签配置