261 lines
10 KiB
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}'),
|
|
];
|
|
}
|
|
}
|