Files
KnowledgeBase/app/Filament/Resources/UserResource.php
lizhuoran 267bb9a36f feat(导航): 优化左侧导航菜单分组结构
调整导航分组,使菜单结构更加清晰合理:

📚 知识库管理(1个菜单)
  1. 文档管理

💼 业务管理(2个菜单)
  1. SOP模板
  2. 终端管理

🔐 权限管理(3个菜单)
  1. 用户管理
  2. 角色管理
  3. 分组管理

⚙️ 系统管理(2个菜单)
  1. 系统设置
  2. 操作日志

优化说明:
- 按照业务逻辑将菜单分为4个主要分组
- 每个分组内的菜单按照使用频率和重要性排序
- 知识库管理独立分组,突出核心功能
- 业务管理包含 SOP 和终端,体现业务流程
- 权限管理集中管理用户、角色、分组
- 系统管理包含系统配置和日志监控

导航结构更加清晰,用户可以快速找到需要的功能模块
2026-03-11 10:29:45 +08:00

310 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\UserResource\Pages;
use App\Filament\Resources\UserResource\RelationManagers;
use App\Models\User;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class UserResource extends Resource
{
protected static ?string $model = User::class;
protected static ?string $navigationIcon = 'heroicon-o-users';
protected static ?string $navigationLabel = '用户管理';
protected static ?string $modelLabel = '用户';
protected static ?string $pluralModelLabel = '用户';
protected static ?int $navigationSort = 1;
protected static ?string $navigationGroup = '权限管理';
/**
* 控制导航菜单是否显示
*/
public static function shouldRegisterNavigation(): bool
{
return auth()->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'),
];
}
}