[FEAT] 實作角色權限分類、租戶角控管理與介面多語系優化
1. [FEAT] 權限劃分為「系統層級」與「客戶層級」,並在後端強制過濾跨權限分配。 2. [FEAT] 整合選單權限至主選單層級 (基本設定、權限設定),簡化角色管理 UI。 3. [STYLE] 側邊欄優化:補齊多語系翻譯,並為基本設定子選單增加視覺圖示。 4. [REFACTOR] 更新 RoleSeeder,將 tenant-admin 重新分類為客戶層級角色。
This commit is contained in:
@@ -25,15 +25,78 @@ class Machine extends Model
|
||||
'firmware_version',
|
||||
'api_token',
|
||||
'last_heartbeat_at',
|
||||
'card_reader_seconds',
|
||||
'card_reader_checkout_time_1',
|
||||
'card_reader_checkout_time_2',
|
||||
'heating_start_time',
|
||||
'heating_end_time',
|
||||
'payment_buffer_seconds',
|
||||
'card_reader_no',
|
||||
'key_no',
|
||||
'invoice_status',
|
||||
'welcome_gift_enabled',
|
||||
'is_spring_slot_1_10',
|
||||
'is_spring_slot_11_20',
|
||||
'is_spring_slot_21_30',
|
||||
'is_spring_slot_31_40',
|
||||
'is_spring_slot_41_50',
|
||||
'is_spring_slot_51_60',
|
||||
'member_system_enabled',
|
||||
'payment_config_id',
|
||||
'machine_model_id',
|
||||
'images',
|
||||
'creator_id',
|
||||
'updater_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'last_heartbeat_at' => 'datetime',
|
||||
'welcome_gift_enabled' => 'boolean',
|
||||
'is_spring_slot_1_10' => 'boolean',
|
||||
'is_spring_slot_11_20' => 'boolean',
|
||||
'is_spring_slot_21_30' => 'boolean',
|
||||
'is_spring_slot_31_40' => 'boolean',
|
||||
'is_spring_slot_41_50' => 'boolean',
|
||||
'is_spring_slot_51_60' => 'boolean',
|
||||
'member_system_enabled' => 'boolean',
|
||||
'images' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get machine images absolute URLs
|
||||
*/
|
||||
public function getImageUrlsAttribute(): array
|
||||
{
|
||||
if (empty($this->images)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(fn($path) => \Illuminate\Support\Facades\Storage::disk('public')->url($path), $this->images);
|
||||
}
|
||||
|
||||
public function logs()
|
||||
{
|
||||
return $this->hasMany(MachineLog::class);
|
||||
}
|
||||
|
||||
public function machineModel()
|
||||
{
|
||||
return $this->belongsTo(MachineModel::class);
|
||||
}
|
||||
|
||||
public function paymentConfig()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\PaymentConfig::class);
|
||||
}
|
||||
|
||||
public function creator()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\User::class, 'creator_id');
|
||||
}
|
||||
|
||||
public function updater()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\User::class, 'updater_id');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
35
app/Models/Machine/MachineModel.php
Normal file
35
app/Models/Machine/MachineModel.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Machine;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MachineModel extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'company_id',
|
||||
'creator_id',
|
||||
'updater_id',
|
||||
];
|
||||
|
||||
public function machines()
|
||||
{
|
||||
return $this->hasMany(Machine::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\Company::class);
|
||||
}
|
||||
|
||||
public function creator()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\User::class, 'creator_id');
|
||||
}
|
||||
|
||||
public function updater()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\User::class, 'updater_id');
|
||||
}
|
||||
}
|
||||
40
app/Models/System/PaymentConfig.php
Normal file
40
app/Models/System/PaymentConfig.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\System;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PaymentConfig extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'company_id',
|
||||
'name',
|
||||
'settings',
|
||||
'creator_id',
|
||||
'updater_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'settings' => 'array',
|
||||
];
|
||||
|
||||
public function machines()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Machine\Machine::class);
|
||||
}
|
||||
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\System\Company::class);
|
||||
}
|
||||
|
||||
public function creator()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'creator_id');
|
||||
}
|
||||
|
||||
public function updater()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updater_id');
|
||||
}
|
||||
}
|
||||
34
app/Models/System/Role.php
Normal file
34
app/Models/System/Role.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\System;
|
||||
|
||||
use Spatie\Permission\Models\Role as SpatieRole;
|
||||
|
||||
class Role extends SpatieRole
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'guard_name',
|
||||
'company_id',
|
||||
'is_system',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the company that owns the role.
|
||||
*/
|
||||
public function company()
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to only include roles for a specific company or system roles.
|
||||
*/
|
||||
public function scopeForCompany($query, $company_id)
|
||||
{
|
||||
return $query->where(function($q) use ($company_id) {
|
||||
$q->where('company_id', $company_id)
|
||||
->orWhereNull('company_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ class User extends Authenticatable
|
||||
*/
|
||||
public function loginLogs()
|
||||
{
|
||||
return $this->hasMany(\App\Models\UserLoginLog::class);
|
||||
return $this->hasMany(UserLoginLog::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
namespace App\Models\System;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; // Added this line
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class UserLoginLog extends Model
|
||||
{
|
||||
Reference in New Issue
Block a user