schema([ // 只读资源,不需要表单 ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('created_at') ->label('操作时间') ->dateTime('Y-m-d H:i:s') ->sortable() ->searchable(), Tables\Columns\TextColumn::make('causer.name') ->label('操作用户') ->searchable() ->sortable() ->default('系统') ->placeholder('系统'), Tables\Columns\TextColumn::make('description') ->label('操作类型') ->badge() ->color(fn (string $state): string => match ($state) { 'created' => 'success', 'updated' => 'info', 'deleted' => 'danger', default => 'gray', }) ->formatStateUsing(fn (string $state): string => match ($state) { 'created' => '创建', 'updated' => '更新', 'deleted' => '删除', default => $state, }) ->searchable() ->sortable(), Tables\Columns\TextColumn::make('subject_type') ->label('操作对象') ->formatStateUsing(function (?string $state): string { if (!$state) { return '-'; } // 提取类名 $className = class_basename($state); // 转换为中文 return match ($className) { 'SystemSetting' => '系统设置', 'User' => '用户', 'Document' => '文档', 'Group' => '分组', 'Terminal' => '终端', 'SopTemplate' => 'SOP模板', default => $className, }; }) ->searchable() ->sortable(), Tables\Columns\TextColumn::make('subject_id') ->label('对象ID') ->searchable() ->sortable() ->toggleable(), Tables\Columns\TextColumn::make('properties') ->label('详情') ->limit(50) ->tooltip(function (Tables\Columns\TextColumn $column): ?string { $state = $column->getState(); if (is_array($state)) { return json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); } return null; }) ->formatStateUsing(function ($state): string { if (is_array($state)) { $summary = []; if (isset($state['attributes'])) { $summary[] = '新值: ' . count($state['attributes']) . '项'; } if (isset($state['old'])) { $summary[] = '旧值: ' . count($state['old']) . '项'; } return implode(', ', $summary) ?: '无变更'; } return '-'; }) ->toggleable(), ]) ->defaultSort('created_at', 'desc') ->filters([ // 时间范围筛选 Tables\Filters\Filter::make('created_at') ->form([ \Filament\Forms\Components\DatePicker::make('created_from') ->label('开始时间') ->placeholder('选择开始时间'), \Filament\Forms\Components\DatePicker::make('created_until') ->label('结束时间') ->placeholder('选择结束时间'), ]) ->query(function ($query, array $data) { return $query ->when($data['created_from'], fn ($query, $date) => $query->whereDate('created_at', '>=', $date)) ->when($data['created_until'], fn ($query, $date) => $query->whereDate('created_at', '<=', $date)); }) ->indicateUsing(function (array $data): array { $indicators = []; if ($data['created_from'] ?? null) { $indicators[] = Tables\Filters\Indicator::make('开始时间: ' . \Carbon\Carbon::parse($data['created_from'])->format('Y-m-d')) ->removeField('created_from'); } if ($data['created_until'] ?? null) { $indicators[] = Tables\Filters\Indicator::make('结束时间: ' . \Carbon\Carbon::parse($data['created_until'])->format('Y-m-d')) ->removeField('created_until'); } return $indicators; }), // 操作类型筛选 Tables\Filters\SelectFilter::make('description') ->label('操作类型') ->options([ 'created' => '创建', 'updated' => '更新', 'deleted' => '删除', ]) ->placeholder('全部类型'), // 用户筛选 Tables\Filters\SelectFilter::make('causer_id') ->label('操作用户') ->options(function () { return \App\Models\User::pluck('name', 'id')->toArray(); }) ->searchable() ->placeholder('全部用户'), // 对象类型筛选 Tables\Filters\SelectFilter::make('subject_type') ->label('对象类型') ->options([ 'App\\Models\\SystemSetting' => '系统设置', 'App\\Models\\User' => '用户', 'App\\Models\\Document' => '文档', 'App\\Models\\Group' => '分组', 'App\\Models\\Terminal' => '终端', 'App\\Models\\SopTemplate' => 'SOP模板', ]) ->placeholder('全部类型'), ]) ->actions([ Tables\Actions\ViewAction::make() ->label('查看'), ]) ->bulkActions([ // 不允许批量操作 ]) ->headerActions([ // 导出操作 Tables\Actions\Action::make('export') ->label('导出日志') ->icon('heroicon-o-arrow-down-tray') ->form([ \Filament\Forms\Components\Select::make('format') ->label('导出格式') ->options([ 'xlsx' => 'Excel (XLSX)', 'csv' => 'CSV', ]) ->default('xlsx') ->required(), ]) ->action(function (array $data) { // 获取基础查询(不包含筛选) $query = Activity::query(); // 导出文件名 $filename = '操作日志_' . now()->format('YmdHis'); // 根据格式导出 if ($data['format'] === 'csv') { return Excel::download( new ActivityLogExport($query), $filename . '.csv', \Maatwebsite\Excel\Excel::CSV ); } return Excel::download( new ActivityLogExport($query), $filename . '.xlsx' ); }) ->color('success') ->requiresConfirmation() ->modalHeading('导出操作日志') ->modalDescription('将导出所有日志数据') ->modalSubmitActionLabel('确认导出'), ]); } public static function getPages(): array { return [ 'index' => Pages\ListActivityLogs::route('/'), 'view' => Pages\ViewActivityLog::route('/{record}'), ]; } }