From 04c9f016bf1fce582d9c36872a163f674654251b Mon Sep 17 00:00:00 2001 From: "allen.yan" Date: Tue, 29 Jul 2025 13:46:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AA=BF=E6=95=B4=E5=8C=85=E5=BB=82Status=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E4=BB=8B=E9=9D=A2=E6=94=B9=E7=B6=AD=E8=AD=B7?= =?UTF-8?q?=2020250729?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commands/CheckRoomOnlineStatus.php | 2 +- app/Enums/RoomStatus.php | 4 +- .../Controllers/RoomControlController.php | 1 + .../Requests/SendRoomSwitchCommandRequest.php | 4 +- .../RoomGridForm.php => Grids/RoomGrid.php} | 6 +- .../{Forms => }/Modals/RoomDetailModal.php | 8 +- app/Livewire/Tables/RoomTable.php | 2 +- app/Services/ApiClient.php | 87 ++++++++++--------- .../2025_05_23_055307_create_rooms_table.php | 2 +- ...3_055312_create_room_status_logs_table.php | 2 +- resources/lang/zh-tw/enums.php | 3 +- resources/lang/zh-tw/rooms.php | 2 +- .../views/components/room-card.blade.php | 4 +- .../views/livewire/admin/room-grids.blade.php | 2 +- .../views/livewire/admin/rooms.blade.php | 2 +- .../room-grid.blade.php} | 2 +- .../modals/room-detail-modal.blade.php | 0 17 files changed, 70 insertions(+), 63 deletions(-) rename app/Livewire/{Forms/RoomGridForm.php => Grids/RoomGrid.php} (88%) rename app/Livewire/{Forms => }/Modals/RoomDetailModal.php (92%) rename resources/views/livewire/{forms/room-grid-form.blade.php => grids/room-grid.blade.php} (97%) rename resources/views/livewire/{forms => }/modals/room-detail-modal.blade.php (100%) diff --git a/app/Console/Commands/CheckRoomOnlineStatus.php b/app/Console/Commands/CheckRoomOnlineStatus.php index 42cb4fa..2e3703e 100644 --- a/app/Console/Commands/CheckRoomOnlineStatus.php +++ b/app/Console/Commands/CheckRoomOnlineStatus.php @@ -21,7 +21,7 @@ class CheckRoomOnlineStatus extends Command $threshold = $now->subMinutes(10); // 所有房間 - $rooms = Room::with('branch')->where('is_online',1)->get(); + $rooms = Room::with('branch')->get(); foreach ($rooms as $room) { $branch = optional($room->branch); diff --git a/app/Enums/RoomStatus.php b/app/Enums/RoomStatus.php index 72ae246..00ef805 100644 --- a/app/Enums/RoomStatus.php +++ b/app/Enums/RoomStatus.php @@ -8,7 +8,7 @@ use App\Enums\Traits\HasLabels; * @OA\Schema( * schema="RoomStatus", * type="string", - * enum={"active", "closed", "fire", "maintenance"}, + * enum={"active", "closed", "fire", "maintain", "error"}, * example="error" * ) */ @@ -18,6 +18,7 @@ enum RoomStatus: string { case Active = 'active'; case Closed = 'closed'; case Fire ='fire'; + case Maintain ='maintain'; case Error = 'error'; // 返回對應的顯示文字 @@ -27,6 +28,7 @@ enum RoomStatus: string { self::Active => __('enums.room.status.Active'), self::Closed => __('enums.room.status.Closed'), self::Fire => __('enums.room.status.Fire'), + self::Maintain => __('enums.room.status.Maintain'), self::Error => __('enums.room.status.Error'), }; } diff --git a/app/Http/Controllers/RoomControlController.php b/app/Http/Controllers/RoomControlController.php index b1f63b3..11c2d14 100644 --- a/app/Http/Controllers/RoomControlController.php +++ b/app/Http/Controllers/RoomControlController.php @@ -264,6 +264,7 @@ class RoomControlController extends Controller $suffix = substr($room->name, -3) ?: $room->name; $signal = match ($validated['command']) { + 'maintain' => 'O', 'active' => 'O', 'closed' => 'X', 'fire' => 'F', diff --git a/app/Http/Requests/SendRoomSwitchCommandRequest.php b/app/Http/Requests/SendRoomSwitchCommandRequest.php index 928d646..d7fc10e 100644 --- a/app/Http/Requests/SendRoomSwitchCommandRequest.php +++ b/app/Http/Requests/SendRoomSwitchCommandRequest.php @@ -10,7 +10,7 @@ use Illuminate\Foundation\Http\FormRequest; * required={"branch_name", "room_name", "command"}, * @OA\Property(property="branch_name", type="string", example="測試"), * @OA\Property(property="room_name", type="string", example="pc102"), - * @OA\Property(property="command", type="string", enum={"active", "closed", "fire", "maintenance"}, example="active"), + * @OA\Property(property="command", type="string", enum={"active", "closed", "fire", "maintain"}, example="active"), * @OA\Property(property="started_at", type="string", nullable=true, example="2025-05-19 09:31:00"), * @OA\Property(property="ended_at", type="string", nullable=true, example="2025-05-19 09:31:00") * ) @@ -27,7 +27,7 @@ class SendRoomSwitchCommandRequest extends ApiRequest return [ 'branch_name' =>'required|string|exists:branches,name', 'room_name' => 'required|string', - 'command' => 'required|string', + 'command' => 'required|in:active,closed,fire,maintain,error', 'started_at' => 'nullable|date_format:Y-m-d H:i:s', 'ended_at' => 'nullable|date_format:Y-m-d H:i:s', ]; diff --git a/app/Livewire/Forms/RoomGridForm.php b/app/Livewire/Grids/RoomGrid.php similarity index 88% rename from app/Livewire/Forms/RoomGridForm.php rename to app/Livewire/Grids/RoomGrid.php index a0b9e90..d0ad6e9 100644 --- a/app/Livewire/Forms/RoomGridForm.php +++ b/app/Livewire/Grids/RoomGrid.php @@ -1,6 +1,6 @@ pluck('floor')->unique()->sort()->values()->toArray(); } - return view('livewire.forms.room-grid-form', [ + return view('livewire.grids.room-grid', [ 'rooms' => $rooms, 'floors' => $floors, ]); diff --git a/app/Livewire/Forms/Modals/RoomDetailModal.php b/app/Livewire/Modals/RoomDetailModal.php similarity index 92% rename from app/Livewire/Forms/Modals/RoomDetailModal.php rename to app/Livewire/Modals/RoomDetailModal.php index 566e161..1f8be3f 100644 --- a/app/Livewire/Forms/Modals/RoomDetailModal.php +++ b/app/Livewire/Modals/RoomDetailModal.php @@ -1,6 +1,6 @@ buildNotifyData('active', now(), null); + $data = $this->buildNotifyData('maintain', null, null); $this->send($data); } @@ -86,7 +86,7 @@ class RoomDetailModal extends Component $this->sendErrorNotification('api', 'API token is missing.'); return false; } - $apiClient = new ApiClient($this->branch->external_ip,$token); + $apiClient = new ApiClient(config('app.url'),$token); $response = $apiClient->post('/api/room/sendSwitch', $data); if ($response->failed()) { $this->sendErrorNotification('api', 'API request failed: ' . $response->body()); @@ -113,6 +113,6 @@ class RoomDetailModal extends Component public function render() { - return view('livewire.forms.modals.room-detail-modal'); + return view('livewire.modals.room-detail-modal'); } } diff --git a/app/Livewire/Tables/RoomTable.php b/app/Livewire/Tables/RoomTable.php index 175887d..fbed69d 100644 --- a/app/Livewire/Tables/RoomTable.php +++ b/app/Livewire/Tables/RoomTable.php @@ -224,7 +224,7 @@ final class RoomTable extends PowerGridComponent ->slot('包廂設定') ->icon('solid-cog') ->class('inline-flex items-center gap-1 px-3 py-1 rounded ') - ->dispatchTo('forms.modals.room-detail-modal', 'openModal', ['roomId' => $row->id]); + ->dispatchTo('modals.room-detail-modal', 'openModal', ['roomId' => $row->id]); } return $actions; } diff --git a/app/Services/ApiClient.php b/app/Services/ApiClient.php index 0da6c09..0b1c19d 100644 --- a/app/Services/ApiClient.php +++ b/app/Services/ApiClient.php @@ -72,12 +72,15 @@ class ApiClient protected function withDefaultHeaders(): PendingRequest { - $request = Http::connectTimeout($this->connectTimeout) - ->timeout($this->timeout) - ->withHeaders([ - 'Accept' => 'application/json', - 'Authorization' => 'Bearer ' . $this->token, - ]); + $request = Http::withOptions([ + 'verify' => false, // ✅ 關閉憑證驗證 + ]) + ->connectTimeout($this->connectTimeout) + ->timeout($this->timeout) + ->withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $this->token, + ]); if ($this->retryTimes > 0) { $request = $request->retry($this->retryTimes, $this->retryDelay, function ($exception, $request) { @@ -95,44 +98,44 @@ class ApiClient } public function requestWithCatch(callable $fn) -{ - try { - return $fn(); - } catch (RequestException $e) { - if ($this->enableLogging) { - Log::error('API Request Failed', [ - 'message' => $e->getMessage(), - 'url' => $e->request?->url(), - 'code' => $e->getCode(), - ]); + { + try { + return $fn(); + } catch (RequestException $e) { + if ($this->enableLogging) { + Log::error('API Request Failed', [ + 'message' => $e->getMessage(), + 'url' => $e->request?->url(), + 'code' => $e->getCode(), + ]); + } + + if ($this->fallbackHandler instanceof \Closure) { + return call_user_func($this->fallbackHandler, $e); + } + + // 智能 fallback,直接寫在這裡 + $status = $e->response?->status(); + + if ($status >= 500) { + return ApiResponse::error('伺服器錯誤,請稍後再試','SERVER_ERROR',503); + } + + if ($status === 404) { + return ApiResponse::error('遠端 API 路徑不存在','API_NOT_FOUND',404); + } + + if ($status === 401 || $status === 403) { + return ApiResponse::unauthorized(); + } + + if ($e->getCode() === 0) { + return ApiResponse::error('無法連線遠端 API(可能超時或 DNS 錯誤)','CONNECTION_ERROR',504); + } + + return ApiResponse::error('API 請求失敗: ' . $e->getMessage(), 'HTTP_CLIENT_ERROR',$status ?? 400); } - - if ($this->fallbackHandler instanceof \Closure) { - return call_user_func($this->fallbackHandler, $e); - } - - // 智能 fallback,直接寫在這裡 - $status = $e->response?->status(); - - if ($status >= 500) { - return ApiResponse::error('伺服器錯誤,請稍後再試','SERVER_ERROR',503); - } - - if ($status === 404) { - return ApiResponse::error('遠端 API 路徑不存在','API_NOT_FOUND',404); - } - - if ($status === 401 || $status === 403) { - return ApiResponse::unauthorized(); - } - - if ($e->getCode() === 0) { - return ApiResponse::error('無法連線遠端 API(可能超時或 DNS 錯誤)','CONNECTION_ERROR',504); - } - - return ApiResponse::error('API 請求失敗: ' . $e->getMessage(), 'HTTP_CLIENT_ERROR',$status ?? 400); } -} public function get(string $endpoint, array $query = []) { diff --git a/database/migrations/2025_05_23_055307_create_rooms_table.php b/database/migrations/2025_05_23_055307_create_rooms_table.php index d376fd4..a90dd54 100644 --- a/database/migrations/2025_05_23_055307_create_rooms_table.php +++ b/database/migrations/2025_05_23_055307_create_rooms_table.php @@ -20,7 +20,7 @@ return new class extends Migration $table->string('internal_ip')->nullable()->comment('內部 IP'); $table->unsignedSmallInteger('port')->nullable()->comment('通訊 Port'); $table->tinyInteger('is_online')->default(0)->comment('連線狀態'); - $table->enum('status', ['active', 'closed','fire', 'error'])->default('error')->comment('狀態'); // :啟用中 / 已結束 + $table->enum('status', ['active', 'closed','fire', 'error','maintain'])->default('error')->comment('狀態'); // :啟用中 / 已結束 $table->dateTime('started_at')->nullable()->comment('開始時間'); // $table->dateTime('ended_at')->nullable()->comment('結束時間'); // $table->timestamps(); diff --git a/database/migrations/2025_05_23_055312_create_room_status_logs_table.php b/database/migrations/2025_05_23_055312_create_room_status_logs_table.php index d602ba8..a9f91b3 100644 --- a/database/migrations/2025_05_23_055312_create_room_status_logs_table.php +++ b/database/migrations/2025_05_23_055312_create_room_status_logs_table.php @@ -15,7 +15,7 @@ return new class extends Migration $table->id(); $table->foreignId('room_id')->nullable(); $table->foreignId('user_id')->nullable(); // 操作者,可為 null(系統) - $table->enum('status', ['active', 'closed','fire', 'error', 'maintenance']); + $table->enum('status', ['active', 'closed','fire', 'error', 'maintain']); $table->text('message')->nullable(); // 可填異常原因或操作說明 $table->timestamps(); }); diff --git a/resources/lang/zh-tw/enums.php b/resources/lang/zh-tw/enums.php index c3ea150..d5c8d77 100644 --- a/resources/lang/zh-tw/enums.php +++ b/resources/lang/zh-tw/enums.php @@ -13,5 +13,6 @@ return [ 'room.status.Active' => '已占用', 'room.status.Closed' => '可用', 'room.status.Fire' => '火災', - 'room.status.Error' => '維修', + 'room.status.Maintain' => '維護', + 'room.status.Error' => '異常', ]; \ No newline at end of file diff --git a/resources/lang/zh-tw/rooms.php b/resources/lang/zh-tw/rooms.php index 154c4f2..310ca87 100644 --- a/resources/lang/zh-tw/rooms.php +++ b/resources/lang/zh-tw/rooms.php @@ -18,7 +18,7 @@ return [ 'ended_at' =>'結束於', 'created_at' =>'建立於', 'active' => '正常', - 'error' => '維修', + 'error' => '關機', 'select_type' =>'選擇型別', diff --git a/resources/views/components/room-card.blade.php b/resources/views/components/room-card.blade.php index 7e9ac81..f90c253 100644 --- a/resources/views/components/room-card.blade.php +++ b/resources/views/components/room-card.blade.php @@ -3,12 +3,12 @@ $statusColors = [ RoomStatus::Active->value => 'green-600', RoomStatus::Closed->value => 'gray-600', - RoomStatus::Error->value => 'red-600', + RoomStatus::Maintain->value => 'red-600', ]; @endphp
+ wire:click="$dispatchTo('modals.room-detail-modal','openModal', { roomId: {{ $room->id }} })"> {{-- 房間名稱 + 線上狀態圓點 --}}