You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel FilamentPHP 3表格如何将签到签出显示在同一行?

在FilamentPHP表格中合并员工签到签出记录为单行显示

要实现将同一员工同一天的签到、签出信息显示在同一行,核心是先通过数据库查询合并数据,再在Filament表格中配置对应列,具体步骤如下:

1. 基础场景实现(单次签到签出)

利用MySQL聚合函数,按employee_id和date分组,提取当天最早时间作为签到时间、最晚时间作为签出时间,直接在Filament Resource中重写表格查询逻辑:

use Illuminate\Support\Facades\DB;
use Filament\Tables\Table;
use App\Models\Attendance;

// 在你的AttendanceResource类中
public static function table(Table $table): Table
{
    return $table
        // 分组合并数据的查询逻辑
        ->query(fn () => Attendance::query()
            ->select([
                'employee_id',
                'date',
                DB::raw('MIN(time) as check_in_time'), // 取当天最早时间为签到
                DB::raw('MAX(time) as check_out_time'), // 取当天最晚时间为签出
            ])
            ->groupBy('employee_id', 'date'))
        // 配置表格列
        ->columns([
            TextColumn::make('employee_id')
                ->label('员工ID'),
            TextColumn::make('date')
                ->label('日期')
                ->date('Y-m-d'),
            TextColumn::make('check_in_time')
                ->label('签到时间')
                ->time('H:i:s'),
            TextColumn::make('check_out_time')
                ->label('签出时间')
                ->time('H:i:s')
                ->default('未签出'), // 处理仅签到未签出的异常情况
        ]);
}

2. 复杂场景适配(多次签到签出)

如果员工同一天存在多轮签到签出(如中途外出返回),上述方法会取全天首尾时间,若需要精准配对每一次签到和签出,可使用MySQL窗口函数关联相邻记录:

// 替换上述query方法中的查询逻辑
->query(fn () => Attendance::query()
    ->select([
        'employee_id',
        'date',
        'time as check_in_time',
        // 关联下一条记录的时间作为对应签出时间
        DB::raw('LEAD(time) OVER (PARTITION BY employee_id, date ORDER BY time) as check_out_time'),
    ])
    // 仅保留每对记录中的签到行
    ->whereRaw('MOD(ROW_NUMBER() OVER (PARTITION BY employee_id, date ORDER BY time), 2) = 1'))

内容的提问来源于stack exchange,提问作者Madushan Serasinghe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 03:15:56