Files
KnowledgeBase/app/Filament/Resources/ActivityLogResource.php

261 lines
10 KiB
PHP

<?php
namespace App\Filament\Resources;
use App\Filament\Resources\ActivityLogResource\Pages;
use App\Exports\ActivityLogExport;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Maatwebsite\Excel\Facades\Excel;
use Spatie\Activitylog\Models\Activity;
class ActivityLogResource extends Resource
{
protected static ?string $model = Activity::class;
protected static ?string $navigationIcon = 'heroicon-o-clipboard-document-list';
protected static ?string $navigationLabel = '操作日志';
protected static ?string $modelLabel = '操作日志';
protected static ?string $pluralModelLabel = '操作日志';
protected static ?int $navigationSort = 2;
protected static ?string $navigationGroup = '系统管理';
/**
* 控制导航菜单是否显示
*/
public static function shouldRegisterNavigation(): bool
{
return auth()->user()?->can('activity-log.view') ?? false;
}
// 禁用创建功能
public static function canCreate(): bool
{
return false;
}
public static function form(Form $form): Form
{
return $form
->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' => '终端',
'Guide' => '操作指引',
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\\Guide' => '操作指引',
])
->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}'),
];
}
}