2026-02-28 23:44:38 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 文件功能:勤务台页面控制器
|
|
|
|
|
|
* 左侧五个子菜单:任职列表、日榜、周榜、月榜、总榜
|
|
|
|
|
|
* 路由:GET /duty-hall?tab=roster|day|week|month|all
|
|
|
|
|
|
*
|
2026-03-01 10:51:48 +08:00
|
|
|
|
* 榜单统计三项指标:
|
|
|
|
|
|
* 1. 在线时长 — position_duty_logs.duration_seconds 合计
|
|
|
|
|
|
* 2. 管理操作次数 — position_authority_logs 非任免类操作次数(warn/kick/mute/banip/other)
|
|
|
|
|
|
* 3. 奖励金币次数 — position_authority_logs WHERE action_type='reward' 的次数及累计金额
|
|
|
|
|
|
*
|
2026-02-28 23:44:38 +08:00
|
|
|
|
* @author ChatRoom Laravel
|
|
|
|
|
|
*
|
2026-03-01 10:51:48 +08:00
|
|
|
|
* @version 1.2.0
|
2026-02-28 23:44:38 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\Department;
|
2026-03-01 10:51:48 +08:00
|
|
|
|
use App\Models\PositionAuthorityLog;
|
2026-02-28 23:44:38 +08:00
|
|
|
|
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');
|
|
|
|
|
|
|
2026-03-01 10:51:48 +08:00
|
|
|
|
// ── 任职列表:按部门→职务展示全部(含空缺) ──────────────────
|
2026-02-28 23:44:38 +08:00
|
|
|
|
$currentStaff = null;
|
|
|
|
|
|
if ($tab === 'roster') {
|
|
|
|
|
|
$currentStaff = Department::query()
|
|
|
|
|
|
->with([
|
|
|
|
|
|
'positions' => fn ($q) => $q->orderByDesc('rank'),
|
|
|
|
|
|
'positions.activeUserPositions.user',
|
|
|
|
|
|
])
|
|
|
|
|
|
->orderByDesc('rank')
|
|
|
|
|
|
->get();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-01 10:51:48 +08:00
|
|
|
|
// ── 日/周/月/总榜:三项指标综合排行 ─────────────────────────
|
2026-02-28 23:44:38 +08:00
|
|
|
|
$leaderboard = null;
|
|
|
|
|
|
if (in_array($tab, ['day', 'week', 'month', 'all'])) {
|
2026-03-01 10:51:48 +08:00
|
|
|
|
|
|
|
|
|
|
// ① 在线时长(position_duty_logs)
|
|
|
|
|
|
$dutyQuery = PositionDutyLog::query()
|
2026-02-28 23:44:38 +08:00
|
|
|
|
->selectRaw('user_id, SUM(duration_seconds) as total_seconds, COUNT(*) as checkin_count');
|
|
|
|
|
|
|
2026-03-01 10:51:48 +08:00
|
|
|
|
// ② 管理操作(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']);
|
|
|
|
|
|
|
|
|
|
|
|
// 按时间段同步过滤两张表
|
2026-02-28 23:44:38 +08:00
|
|
|
|
match ($tab) {
|
2026-03-01 10:51:48 +08:00
|
|
|
|
'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, // 不限制时间
|
2026-02-28 23:44:38 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-03-01 10:51:48 +08:00
|
|
|
|
// 执行查询
|
|
|
|
|
|
$dutyRows = $dutyQuery
|
2026-02-28 23:44:38 +08:00
|
|
|
|
->groupBy('user_id')
|
|
|
|
|
|
->orderByDesc('total_seconds')
|
|
|
|
|
|
->limit(20)
|
|
|
|
|
|
->with('user')
|
|
|
|
|
|
->get();
|
2026-03-01 10:51:48 +08:00
|
|
|
|
|
|
|
|
|
|
// 管理操作数据(按 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;
|
|
|
|
|
|
});
|
2026-02-28 23:44:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 各榜标签配置
|
|
|
|
|
|
$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',
|
|
|
|
|
|
));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|