diff --git a/app/Http/Controllers/RoomControlController.php b/app/Http/Controllers/RoomControlController.php index a25ae43..0d635bc 100644 --- a/app/Http/Controllers/RoomControlController.php +++ b/app/Http/Controllers/RoomControlController.php @@ -97,7 +97,8 @@ class RoomControlController extends Controller return ApiResponse::error('包廂不存在'); } $command = $validated['command']; - + $room->log_source='api'; + $room->log_message='sendSwitch'; $room->update([ 'status' => $command, 'started_at' => $validated['started_at'] ?? null, @@ -137,6 +138,8 @@ class RoomControlController extends Controller ])->first(); if ($room) { // 更新 + $room->log_source='api'; + $room->log_message='receiveSwitch'; $room->update([ 'is_online' => $validated['is_online'], 'status' => $validated['status'], @@ -146,7 +149,7 @@ class RoomControlController extends Controller //Log::info('Room updated', ['room_id' => $room->id, 'name' => $room->name]); } else { // 新增 - $room = Room::create([ + $room = new Room([ 'branch_id' => $validated['branch_id'], 'floor' => $validated['floor'], 'type' => $validated['type'], @@ -156,6 +159,9 @@ class RoomControlController extends Controller 'started_at' => $validated['started_at'], 'ended_at' => $validated['ended_at'], ]); + $room->log_source = 'api'; + $room->log_message = 'receiveSwitch'; + $room->save(); //Log::info('Room created', ['room_id' => $room->id, 'name' => $room->name]); } return ApiResponse::success(new RoomResource($room->refresh())); diff --git a/app/Livewire/Forms/RoomForm.php b/app/Livewire/Forms/RoomForm.php deleted file mode 100644 index f6307aa..0000000 --- a/app/Livewire/Forms/RoomForm.php +++ /dev/null @@ -1,125 +0,0 @@ -'', - 'type' =>'', - 'name' =>'' - ]; - - - public function mount() - { - $this->typeOptions = collect(RoomType::cases())->map(fn ($type) => [ - 'name' => $type->labels(), - 'value' => $type->value, - ])->toArray(); - $this->canCreate = Auth::user()?->can('room-edit') ?? false; - $this->canEdit = Auth::user()?->can('room-edit') ?? false; - $this->canDelect = Auth::user()?->can('room-delete') ?? false; - } - - public function openModal($id = null) - { - $this->resetFields(); - - if ($id) { - $room = Room::findOrFail($id); - $this->roomId = $room->id; - $this->fields = $room->only(array_keys($this->fields)); - } - - $this->showModal = true; - } - - public function closeModal() - { - $this->resetFields(); - $this->showModal = false; - } - - public function save() - { - $description ="無權修改"; - if ($this->roomId) { - if ($this->canEdit) { - $room = Room::findOrFail($this->roomId); - $room->update($this->fields); - $description='分店已更新'; - } - } else { - if ($this->canCreate) { - $room = Room::create([ - 'floor' => $this->fields['floor'], - 'type' => $this->fields['type'], - 'name' => $this->fields['name'], - ]); - $description='分店已新增'; - } - } - $this->notification()->send([ - 'icon' => 'success', - 'title' => '成功', - 'description' => $description, - ]); - $this->resetFields(); - $this->showModal = false; - $this->dispatch('pg:eventRefresh-room-table'); - } - - public function deleteBranch($id) - { - if ($this->canDelect) { - Room::findOrFail($id)->delete(); - $this->notification()->send([ - 'icon' => 'success', - 'title' => '成功', - 'description' => '分店已刪除', - ]); - - $this->dispatch('pg:eventRefresh-room-table'); - } - } - - public function resetFields() - { - foreach ($this->fields as $key => $value) { - if ($key == 'enable') { - $this->fields[$key] = true; - } else { - $this->fields[$key] = ''; - } - } - $this->branchId = null; - } - - public function render() - { - return view('livewire.forms.room-form'); - } -} diff --git a/app/Livewire/Tables/RoomStatusLogTable.php b/app/Livewire/Tables/RoomStatusLogTable.php index 0e71dc3..1f597e0 100644 --- a/app/Livewire/Tables/RoomStatusLogTable.php +++ b/app/Livewire/Tables/RoomStatusLogTable.php @@ -37,28 +37,39 @@ final class RoomStatusLogTable extends PowerGridComponent public function datasource(): Builder { - return RoomStatusLog::query()->latest();; + return RoomStatusLog::with(['room', 'branch'])->latest(); } public function relationSearch(): array { - return []; + return [ + 'branch' => ['name'], + 'room' => ['name'], + 'user' => ['name'], + ]; } public function fields(): PowerGridFields { return PowerGrid::fields() ->add('id') + ->add('branch_name', function (RoomStatusLog $model) { + return $model->branch?->name; + }) ->add('room_name', function (RoomStatusLog $model) { return $model->room?->type->labelPowergridFilter().$model->room?->name; }) ->add('user_name', function (RoomStatusLog $model){ return $model->user?->name; }) + ->add('is_online') ->add('status_str',function (RoomStatusLog $model){ return $model->status->labelPowergridFilter(); }) + ->add('started_at') + ->add('ended_at') ->add('message') + ->add('source') ->add('created_at'); } @@ -66,10 +77,15 @@ final class RoomStatusLogTable extends PowerGridComponent { $column=[]; $column[]=Column::make(__('room-status-log.id'), 'id'); + $column[]=Column::make(__('room-status-log.branch'), 'branch_name'); $column[]=Column::make(__('room-status-log.room'), 'room_name'); $column[]=Column::make(__('room-status-log.user'), 'user_name'); + $column[]=Column::make(__('room-status-log.is_online'), 'is_online'); $column[]=Column::make(__('room-status-log.status'), 'status_str'); + $column[]=Column::make(__('room-status-log.started_at'), 'started_at'); + $column[]=Column::make(__('room-status-log.ended_at'), 'ended_at'); $column[]=Column::make(__('room-status-log.message'), 'message'); + $column[]=Column::make(__('room-status-log.source'), 'source'); $column[]=Column::make(__('room-status-log.created_at'), 'created_at'); return $column; } @@ -77,6 +93,7 @@ final class RoomStatusLogTable extends PowerGridComponent public function filters(): array { return [ + ]; } } diff --git a/app/Livewire/Tables/RoomTable.php b/app/Livewire/Tables/RoomTable.php index 82217e0..92493c7 100644 --- a/app/Livewire/Tables/RoomTable.php +++ b/app/Livewire/Tables/RoomTable.php @@ -24,8 +24,6 @@ final class RoomTable extends PowerGridComponent { use WithExport, WireUiActions; public string $tableName = 'room-table'; - public bool $canCreate; - public bool $canEdit; public bool $canDownload; public bool $canDelect; public ?int $selectedBranchId = null; @@ -36,8 +34,6 @@ final class RoomTable extends PowerGridComponent { config(['livewire-powergrid.filter' => 'outside']); //權限設定 - $this->canCreate = Auth::user()?->can('room-edit') ?? false; - $this->canEdit = Auth::user()?->can('room-edit') ?? false; $this->canDownload=Auth::user()?->can('room-delete') ?? false; $this->canDelect = Auth::user()?->can('room-delete') ?? false; $branch = Branch::first(); @@ -58,9 +54,7 @@ final class RoomTable extends PowerGridComponent $header = PowerGrid::header() ->withoutLoading() ->showToggleColumns(); - if($this->canCreate){ - $header->includeViewOnTop('livewire.forms.headers.room'); - } + $header->includeViewOnTop('livewire.forms.headers.room'); $actions[]=$header; $actions[]=PowerGrid::footer()->showPerPage()->showRecordCount(); return $actions; @@ -104,17 +98,6 @@ final class RoomTable extends PowerGridComponent ->add('id') ->add('floor') ->add('type_str',function(Room $model){ - if ($this->canEdit) { - return Blade::render( - '', - [ - 'options' => RoomType::options(), - 'modelId' => intval($model->id), - 'fieldName'=>'type', - 'selected' => $model->type->value - ] - ); - } return $model->type->labelPowergridFilter(); }) ->add('name') @@ -131,20 +114,9 @@ final class RoomTable extends PowerGridComponent { $column=[]; $column[]=Column::make(__('rooms.id'), 'id'); - $column[]=Column::make(__('rooms.floor'), 'floor')->sortable()->searchable()->editOnClick( - hasPermission: $this->canEdit, - dataField: 'floor', - fallback: 'N/A', - saveOnMouseOut: true - ); + $column[]=Column::make(__('rooms.floor'), 'floor')->sortable()->searchable(); $column[]=Column::make(__('rooms.type'), 'type_str','room.type')->sortable()->searchable(); - $column[]=Column::make(__('rooms.name'), 'name')->sortable()->searchable() - ->editOnClick( - hasPermission: $this->canEdit, - dataField: 'name', - fallback: 'N/A', - saveOnMouseOut: true - ); + $column[]=Column::make(__('rooms.name'), 'name')->sortable()->searchable(); $column[]=Column::make(__('rooms.isOnline'), 'is_online'); $column[]=Column::make(__('rooms.status'), 'status_str','room.status')->sortable()->searchable()->hidden(true, false); $column[]=Column::make(__('rooms.started_at'), 'str_started_at', 'started_at')->sortable()->hidden(true, false); @@ -186,58 +158,32 @@ final class RoomTable extends PowerGridComponent $branch = Branch::find($this->selectedBranchId); $this->external_ip=$branch->external_ip; } - if ($fieldName == 'type' && $this->canEdit) { - $this->noUpdated($modelId,$fieldName,$value); - } } - #[On('onUpdatedEditable')] - public function onUpdatedEditable($id, $field, $value): void + #[On('deleteRoom')] + public function deleteRoom($rowId) { - if($field === 'floor' && $this->canEdit){ - if (!is_numeric($value)) { - $this->notification()->send([ - 'icon' => 'error', - 'title' => '無效輸入', - 'description' => '樓層必須是數字', - ]); - return; - } - $this->noUpdated($id,$field,$value); - }else if ($field === 'name' && $this->canEdit) { - $this->noUpdated($id,$field,$value); + if ($this->canDelect) { + Room::findOrFail($rowId)->delete(); + $this->notification()->send([ + 'icon' => 'success', + 'title' => '成功', + 'description' => '包廂已刪除', + ]); + + $this->dispatch('pg:eventRefresh-room-table'); } } - - private function noUpdated($id,$field,$value){ - $room = Room::find($id); - if ($room) { - $room->{$field} = $value; - $room->save(); // 明確觸發 saving - } - $this->notification()->send([ - 'icon' => 'success', - 'title' => $id.'.'.__('room.'.$field).':'.$value, - 'description' => '已經寫入', - ]); - } public function actions(Room $row): array { $actions = []; - if ($this->canEdit) { - $actions[] =Button::add('edit') - ->slot(__('rooms.edit')) - ->icon('solid-pencil-square') - ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') - ->dispatchTo('forms.room-form', 'openModal', ['id' => $row->id]); - } if($this->canDelect){ $actions[] =Button::add('delete') ->slot(__('rooms.delete')) ->icon('solid-trash') ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') - ->dispatchTo('forms.room-form', 'deleteRoom', ['id' => $row->id]); + ->dispatch('deleteRoom', ['rowId' => $row->id]); } if ($row->type->value === 'pc') { $actions[] = Button::add('room-settings') diff --git a/app/Models/Room.php b/app/Models/Room.php index de896a2..11edf97 100644 --- a/app/Models/Room.php +++ b/app/Models/Room.php @@ -27,6 +27,9 @@ class Room extends Model /** @use HasFactory<\Database\Factories\ArtistFactory> */ use HasFactory, LogsModelActivity; + public string $log_message = 'BranchForm-add'; + public string $log_source = 'manual'; + protected $fillable = [ 'branch_id', 'floor', @@ -55,7 +58,6 @@ class Room extends Model 'status' => \App\Enums\RoomStatus::class, 'started_at' => 'datetime', 'ended_at' => 'datetime', - ]; public function str_started_at(){ diff --git a/app/Models/RoomStatusLog.php b/app/Models/RoomStatusLog.php index 1c7dca5..7c7f7b2 100644 --- a/app/Models/RoomStatusLog.php +++ b/app/Models/RoomStatusLog.php @@ -13,18 +13,30 @@ class RoomStatusLog extends Model protected $fillable = [ + 'branch_id', 'room_id', 'user_id', + 'is_online', 'status', + 'started_at', + 'ended_at', 'message', + 'source', ]; protected $casts = [ + 'is_online' => 'boolean', 'status' => \App\Enums\RoomStatus::class, + 'started_at' => 'datetime', + 'ended_at' => 'datetime', + ]; public function user(){ return $this->belongsTo(User::class); } + public function branch() { + return $this->belongsTo(Branch::class); + } public function room() { return $this->belongsTo(Room::class); } diff --git a/app/Observers/RoomObserver.php b/app/Observers/RoomObserver.php index d8a3649..f359712 100644 --- a/app/Observers/RoomObserver.php +++ b/app/Observers/RoomObserver.php @@ -3,6 +3,7 @@ namespace App\Observers; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Arr; use App\Models\Room; use App\Models\RoomStatusLog; @@ -14,7 +15,17 @@ class RoomObserver */ public function created(Room $room): void { - // + RoomStatusLog::create([ + 'branch_id' => $room->branch->id, + 'room_id' => $room->id, + 'user_id' => Auth::id()?? 0, + 'is_online' => $room->is_online, + 'status' => $room->status ?? 'error', + 'started_at' => $room->started_at, + 'ended_at' => $room->ended_at, + 'message' => $room->log_message ?? '', + 'source' => $this->getSource($room), + ]); } /** @@ -23,12 +34,17 @@ class RoomObserver public function updated(Room $room): void { // 檢查是否有變更狀態 - if ($room->wasChanged('status')) { + if ($room->wasChanged()) { RoomStatusLog::create([ + 'branch_id' => $room->branch->id, 'room_id' => $room->id, - 'user_id' => Auth::id(), // 若是 console 或系統自動操作可能為 null + 'user_id' => Auth::id() ?? 0, + 'is_online' => $room->is_online, 'status' => $room->status, - 'message' => 'started_at:'.$room->started_at.',ended_at:'.$room->ended_at, + 'started_at' =>$room->started_at, + 'ended_at' =>$room->ended_at, + 'message' => $room->log_message ?? '', + 'source' => $this->getSource($room), ]); } } @@ -38,7 +54,25 @@ class RoomObserver */ public function deleted(Room $room): void { - // + $message = sprintf( + "%s:%s%s (%s:%s) 已刪除", + $room->branch->name, + $room->type->value, + $room->name, + $room->internal_ip, + $room->port + ); + RoomStatusLog::create([ + 'branch_id' => $room->branch->id, + 'room_id' => $room->id, + 'user_id' => Auth::id() ?? 0, + 'is_online' => $room->is_online, + 'status' => $room->status, + 'started_at' =>$room->started_at, + 'ended_at' =>$room->ended_at, + 'message' => $message, + 'source' => $this->getSource($room), + ]); } /** @@ -56,4 +90,9 @@ class RoomObserver { // } + + private function getSource(Room $room): string + { + return app()->runningInConsole() ? 'system' : ($room->log_source ?? 'manual'); + } } diff --git a/database/migrations/2025_05_06_055312_create_room_status_logs_table.php b/database/migrations/2025_07_30_105320_create_room_status_logs_table.php similarity index 55% rename from database/migrations/2025_05_06_055312_create_room_status_logs_table.php rename to database/migrations/2025_07_30_105320_create_room_status_logs_table.php index 59f2d25..37bb00a 100644 --- a/database/migrations/2025_05_06_055312_create_room_status_logs_table.php +++ b/database/migrations/2025_07_30_105320_create_room_status_logs_table.php @@ -13,10 +13,19 @@ return new class extends Migration { Schema::create('room_status_logs', function (Blueprint $table) { $table->id(); - $table->foreignId('room_id')->constrained()->onDelete('cascade'); - $table->foreignId('user_id')->nullable()->constrained()->onDelete('set null'); // 操作者,可為 null(系統) + $table->unsignedBigInteger('branch_id'); + $table->unsignedBigInteger('room_id'); + $table->unsignedBigInteger('user_id'); + $table->tinyInteger('is_online')->default(0); $table->enum('status', ['active', 'closed','fire', 'error', 'maintain']); + $table->timestamp('started_at')->nullable(); + $table->timestamp('ended_at')->nullable(); $table->text('message')->nullable(); // 可填異常原因或操作說明 + $table->enum('source', ['system', 'manual', 'api'])->default('manual'); + $table->index('branch_id'); + $table->index('room_id'); + $table->index('user_id'); + $table->index('started_at'); $table->timestamps(); }); } diff --git a/resources/lang/zh-tw/room-status-log.php b/resources/lang/zh-tw/room-status-log.php index 40ae803..976e12a 100644 --- a/resources/lang/zh-tw/room-status-log.php +++ b/resources/lang/zh-tw/room-status-log.php @@ -4,10 +4,15 @@ return [ 'list' => '包廂狀態紀錄', 'id' => '編號', + 'branch' => '分店', 'room' => '包廂', 'user' => '操成者', + 'is_online' => '在線?', 'status' => '狀態', + 'started_at' => '開始於', + 'ended_at' => '結束於', 'message' => '紀錄', + 'source' => '來源', 'created_at' => '建立於' ]; \ No newline at end of file diff --git a/resources/views/livewire/admin/rooms.blade.php b/resources/views/livewire/admin/rooms.blade.php index 9a0ed68..018e598 100644 --- a/resources/views/livewire/admin/rooms.blade.php +++ b/resources/views/livewire/admin/rooms.blade.php @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/resources/views/livewire/forms/headers/room.blade.php b/resources/views/livewire/forms/headers/room.blade.php index 918656c..dadd343 100644 --- a/resources/views/livewire/forms/headers/room.blade.php +++ b/resources/views/livewire/forms/headers/room.blade.php @@ -1,10 +1,2 @@ - @if ($canCreate) - - @endif \ No newline at end of file diff --git a/resources/views/livewire/forms/room-form.blade.php b/resources/views/livewire/forms/room-form.blade.php deleted file mode 100644 index f2579a6..0000000 --- a/resources/views/livewire/forms/room-form.blade.php +++ /dev/null @@ -1,21 +0,0 @@ - -
- - - -
- -
- - -
-
-
- \ No newline at end of file