[FEAT] 優化帳號管理授權顯示邏輯與 UI 樣式一致性
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 59s
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 59s
This commit is contained in:
@@ -3,6 +3,16 @@
|
||||
@section('content')
|
||||
<div class="space-y-6" x-data="{
|
||||
selectedPermissions: {{ json_encode($role->permissions->pluck('name')->toArray()) }},
|
||||
@php
|
||||
$availablePermissions = $all_permissions->flatten();
|
||||
if (!$role->is_system) {
|
||||
$availablePermissions = $availablePermissions->filter(function($p) {
|
||||
return !str_starts_with($p->name, 'menu.basic') &&
|
||||
!str_starts_with($p->name, 'menu.permissions');
|
||||
});
|
||||
}
|
||||
@endphp
|
||||
availableCount: {{ $availablePermissions->count() }},
|
||||
activeCategory: '',
|
||||
toggleCategory(category, permissions) {
|
||||
const allSelected = permissions.every(p => this.selectedPermissions.includes(p));
|
||||
@@ -20,6 +30,32 @@
|
||||
const selectedCount = permissions.filter(p => this.selectedPermissions.includes(p)).length;
|
||||
return selectedCount > 0 && selectedCount < permissions.length;
|
||||
},
|
||||
toggleParent(parentName, childrenNames) {
|
||||
const isSelected = this.selectedPermissions.includes(parentName);
|
||||
if (isSelected) {
|
||||
// 取消父項目與所有子項目
|
||||
this.selectedPermissions = this.selectedPermissions.filter(p => p !== parentName && !childrenNames.includes(p));
|
||||
} else {
|
||||
// 勾選父項目
|
||||
if (!this.selectedPermissions.includes(parentName)) {
|
||||
this.selectedPermissions.push(parentName);
|
||||
}
|
||||
// 勾選所有尚未勾選的子項目
|
||||
childrenNames.forEach(p => {
|
||||
if (!this.selectedPermissions.includes(p)) this.selectedPermissions.push(p);
|
||||
});
|
||||
}
|
||||
},
|
||||
isParentSelected(parentName, childrenNames) {
|
||||
return this.selectedPermissions.includes(parentName) &&
|
||||
childrenNames.every(p => this.selectedPermissions.includes(p));
|
||||
},
|
||||
isParentPartial(parentName, childrenNames) {
|
||||
const hasParent = this.selectedPermissions.includes(parentName);
|
||||
const selectedChildrenCount = childrenNames.filter(p => this.selectedPermissions.includes(p)).length;
|
||||
return (hasParent && selectedChildrenCount < childrenNames.length) ||
|
||||
(!hasParent && selectedChildrenCount > 0);
|
||||
},
|
||||
scrollTo(id) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
@@ -140,7 +176,7 @@
|
||||
<span class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-1">{{ __('Total Selected') }}</span>
|
||||
<div class="flex items-baseline gap-1">
|
||||
<span class="text-3xl font-display font-black text-cyan-500" x-text="selectedPermissions.length">0</span>
|
||||
<span class="text-xs font-bold text-slate-400">/ {{ $all_permissions->flatten()->count() }}</span>
|
||||
<span class="text-xs font-bold text-slate-400">/ <span x-text="availableCount"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-12 h-12 rounded-2xl bg-emerald-500/5 flex items-center justify-center text-emerald-500">
|
||||
@@ -156,6 +192,13 @@
|
||||
<div class="flex-1 w-full space-y-12">
|
||||
@foreach($all_permissions as $group => $permissions)
|
||||
@php
|
||||
// 如果非系統角色,過濾掉敏感權限
|
||||
if (!$role->is_system && $group === 'menu') {
|
||||
$permissions = $permissions->filter(function($p) {
|
||||
return !str_starts_with($p->name, 'menu.basic') &&
|
||||
!str_starts_with($p->name, 'menu.permissions');
|
||||
});
|
||||
}
|
||||
$groupId = 'group-' . $group;
|
||||
$groupPermissions = $permissions->pluck('name')->toArray();
|
||||
@endphp
|
||||
@@ -218,9 +261,11 @@
|
||||
<div class="flex items-center pr-1">
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" name="permissions[]" value="{{ $parent->name }}"
|
||||
x-model="selectedPermissions"
|
||||
:checked="selectedPermissions.includes('{{ $parent->name }}')"
|
||||
@change="toggleParent('{{ $parent->name }}', {{ json_encode($children->pluck('name')->toArray()) }})"
|
||||
class="sr-only peer">
|
||||
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:outline-none peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500 transition-all duration-200 shadow-inner"></div>
|
||||
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:outline-none peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500 transition-all duration-200 shadow-inner"
|
||||
:class="isParentPartial('{{ $parent->name }}', {{ json_encode($children->pluck('name')->toArray()) }}) ? 'ring-2 ring-cyan-500/50' : ''"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -237,9 +282,9 @@
|
||||
<div class="relative flex items-center flex-shrink-0">
|
||||
<input type="checkbox"
|
||||
name="permissions[]"
|
||||
value="{{ $child->id }}"
|
||||
class="w-4 h-4 rounded border-2 border-slate-300 dark:border-slate-700 text-cyan-500 focus:ring-cyan-500/20 transition-all cursor-pointer accent-cyan-500"
|
||||
{{ $role->hasPermissionTo($child->name) ? 'checked' : '' }}>
|
||||
value="{{ $child->name }}"
|
||||
x-model="selectedPermissions"
|
||||
class="w-4 h-4 rounded border-2 border-slate-300 dark:border-slate-700 text-cyan-500 focus:ring-cyan-500/20 transition-all cursor-pointer accent-cyan-500">
|
||||
</div>
|
||||
</label>
|
||||
@endforeach
|
||||
|
||||
@@ -66,13 +66,16 @@
|
||||
|
||||
@if(auth()->user()->isSystemAdmin())
|
||||
<div class="relative">
|
||||
<select name="company_id" onchange="this.form.submit()" class="py-2.5 pl-4 pr-10 block w-full md:w-60 luxury-input">
|
||||
<option value="">{{ __('All Affiliations') }}</option>
|
||||
<option value="system" {{ request('company_id') === 'system' ? 'selected' : '' }}>{{ __('System Level') }}</option>
|
||||
@foreach($companies as $company)
|
||||
<option value="{{ $company->id }}" {{ request('company_id') == $company->id ? 'selected' : '' }}>{{ $company->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<x-searchable-select
|
||||
name="company_id"
|
||||
:options="$companies"
|
||||
:selected="request('company_id')"
|
||||
placeholder="{{ __('All Affiliations') }}"
|
||||
class="w-full md:w-auto min-w-[280px]"
|
||||
onchange="this.form.submit()"
|
||||
>
|
||||
<option value="system" {{ request('company_id') === 'system' ? 'selected' : '' }} data-title="{{ __('System Level') }}">{{ __('System Level') }}</option>
|
||||
</x-searchable-select>
|
||||
</div>
|
||||
@endif
|
||||
<input type="hidden" name="per_page" value="{{ request('per_page', 10) }}">
|
||||
@@ -108,11 +111,11 @@
|
||||
</td>
|
||||
<td class="px-6 py-6">
|
||||
@if($role->is_system)
|
||||
<span class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-slate-800 uppercase tracking-wider">
|
||||
<span class="px-2.5 py-1 rounded-lg text-xs font-bold bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 uppercase tracking-widest">
|
||||
{{ __('System Level') }}
|
||||
</span>
|
||||
@else
|
||||
<span class="inline-flex items-center px-2.5 py-1 rounded-lg text-xs font-bold bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border border-emerald-500/20 tracking-wider">
|
||||
<span class="text-xs font-bold text-slate-500 dark:text-slate-400 tracking-widest uppercase">
|
||||
{{ $role->company->name ?? __('Company Level') }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
Reference in New Issue
Block a user