user()?->can('user.view') ?? false; } /** * 获取权限分组标签页 */ protected static function getPermissionTabs(): array { // 模块名称和图标映射 $moduleConfig = [ 'document' => ['name' => '文档管理', 'icon' => 'heroicon-o-document-text'], 'system-setting' => ['name' => '系统设置', 'icon' => 'heroicon-o-cog-6-tooth'], 'activity-log' => ['name' => '操作日志', 'icon' => 'heroicon-o-clipboard-document-list'], 'terminal' => ['name' => '终端管理', 'icon' => 'heroicon-o-computer-desktop'], 'sop-template' => ['name' => 'SOP模板', 'icon' => 'heroicon-o-document-text'], 'group' => ['name' => '分组管理', 'icon' => 'heroicon-o-user-group'], 'user' => ['name' => '用户管理', 'icon' => 'heroicon-o-users'], 'role' => ['name' => '角色管理', 'icon' => 'heroicon-o-shield-check'], ]; // 操作名称映射 $actionNames = [ 'viewAny' => '查看列表', 'view' => '查看详情', 'create' => '创建', 'update' => '编辑', 'delete' => '删除', 'download' => '下载', 'export' => '导出', 'sync' => '同步', 'publish' => '发布', 'archive' => '归档', ]; // 按模块分组权限 $groupedPermissions = \Spatie\Permission\Models\Permission::all() ->groupBy(function ($permission) { return explode('.', $permission->name)[0]; }); $tabs = []; foreach ($groupedPermissions as $module => $permissions) { $config = $moduleConfig[$module] ?? ['name' => $module, 'icon' => 'heroicon-o-square-3-stack-3d']; // 构建该模块的权限选项 $options = $permissions->mapWithKeys(function ($permission) use ($actionNames) { $action = explode('.', $permission->name)[1] ?? ''; $actionName = $actionNames[$action] ?? $action; return [$permission->name => $actionName]; })->toArray(); $tabs[] = Forms\Components\Tabs\Tab::make($config['name']) ->icon($config['icon']) ->schema([ Forms\Components\CheckboxList::make("permissions_{$module}") ->label('') ->options($options) ->columns(2) ->bulkToggleable() ->helperText('选择该模块的直接权限(会叠加到角色权限之上)') ->afterStateHydrated(function ($component, $state, ?User $record) use ($module) { if ($record) { // 获取该用户在当前模块的直接权限 $modulePermissions = $record->permissions() ->where('name', 'like', "{$module}.%") ->pluck('name') ->toArray(); $component->state($modulePermissions); } }) ->dehydrated(false), // 不直接保存,在下面统一处理 ]); } return $tabs; } public static function form(Form $form): Form { return $form ->schema([ Forms\Components\Section::make('基本信息') ->schema([ Forms\Components\TextInput::make('name') ->label('用户名称') ->required() ->maxLength(255) ->placeholder('请输入用户名称'), Forms\Components\TextInput::make('email') ->label('邮箱') ->email() ->required() ->maxLength(255) ->placeholder('请输入邮箱地址'), Forms\Components\TextInput::make('password') ->label('密码') ->password() ->required(fn (string $context): bool => $context === 'create') ->dehydrated(fn ($state) => filled($state)) ->minLength(8) ->placeholder('请输入密码(至少8位)') ->helperText('编辑时留空表示不修改密码'), ]) ->columns(2), Forms\Components\Section::make('分组与角色') ->schema([ Forms\Components\Select::make('groups') ->label('所属分组') ->multiple() ->relationship('groups', 'name') ->preload() ->placeholder('请选择用户所属的分组') ->helperText('用户可以属于多个分组'), Forms\Components\Select::make('roles') ->label('角色') ->multiple() ->relationship('roles', 'name') ->preload() ->placeholder('请选择用户角色') ->helperText('角色决定用户的基础权限') ->searchable(), ]) ->columns(2), Forms\Components\Section::make('直接权限') ->description('为用户分配额外的权限,这些权限会叠加到角色权限之上') ->schema([ Forms\Components\Hidden::make('all_permissions') ->afterStateHydrated(function ($component, ?User $record) { if ($record) { $component->state($record->permissions->pluck('name')->toArray()); } }) ->dehydrateStateUsing(function ($state, $get) { // 收集所有模块的权限 $allPermissions = []; $modules = ['document', 'system-setting', 'activity-log', 'terminal', 'sop-template', 'group', 'user', 'role']; foreach ($modules as $module) { $modulePermissions = $get("permissions_{$module}") ?? []; $allPermissions = array_merge($allPermissions, $modulePermissions); } return $allPermissions; }), Forms\Components\Tabs::make('权限分组') ->tabs(self::getPermissionTabs()) ->columnSpanFull(), ]) ->collapsible() ->collapsed(), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') ->sortable(), Tables\Columns\TextColumn::make('name') ->label('用户名称') ->searchable() ->sortable(), Tables\Columns\TextColumn::make('email') ->label('邮箱') ->searchable() ->sortable(), Tables\Columns\TextColumn::make('roles.name') ->label('角色') ->badge() ->color(fn (string $state): string => match ($state) { 'super-admin' => 'danger', 'admin' => 'warning', 'user' => 'success', default => 'gray', }) ->formatStateUsing(fn (string $state): string => match ($state) { 'super-admin' => '超级管理员', 'admin' => '管理员', 'user' => '普通用户', default => $state, }) ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('groups.name') ->label('所属分组') ->badge() ->searchable() ->toggleable(), Tables\Columns\TextColumn::make('permissions_count') ->label('权限数量') ->counts('permissions') ->sortable() ->toggleable(), Tables\Columns\TextColumn::make('created_at') ->label('创建时间') ->dateTime('Y-m-d H:i:s') ->sortable() ->toggleable(), Tables\Columns\TextColumn::make('updated_at') ->label('更新时间') ->dateTime('Y-m-d H:i:s') ->sortable() ->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ Tables\Filters\SelectFilter::make('roles') ->label('角色') ->relationship('roles', 'name') ->multiple() ->preload(), ]) ->actions([ Tables\Actions\ViewAction::make() ->label('查看'), Tables\Actions\EditAction::make() ->label('编辑'), Tables\Actions\DeleteAction::make() ->label('删除') ->before(function (Tables\Actions\DeleteAction $action, User $record) { // 防止删除超级管理员 if ($record->isSuperAdmin()) { \Filament\Notifications\Notification::make() ->danger() ->title('无法删除') ->body('不能删除超级管理员账户') ->send(); $action->cancel(); } }), ]) ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make() ->label('批量删除') ->before(function (Tables\Actions\DeleteBulkAction $action, $records) { // 检查是否包含超级管理员 $hasSuperAdmin = $records->contains(fn ($record) => $record->isSuperAdmin()); if ($hasSuperAdmin) { \Filament\Notifications\Notification::make() ->danger() ->title('无法删除') ->body('选中的用户中包含超级管理员,无法批量删除') ->send(); $action->cancel(); } }), ]), ]) ->defaultSort('created_at', 'desc'); } public static function getRelations(): array { return [ RelationManagers\GroupsRelationManager::class, ]; } public static function getPages(): array { return [ 'index' => Pages\ListUsers::route('/'), 'create' => Pages\CreateUser::route('/create'), 'view' => Pages\ViewUser::route('/{record}'), 'edit' => Pages\EditUser::route('/{record}/edit'), ]; } }