input('per_page', 10); $query = Machine::query(); // 搜尋:名稱或序號 if ($search = $request->input('search')) { $query->where(function ($q) use ($search) { $q->where('name', 'like', "%{$search}%") ->orWhere('serial_no', 'like', "%{$search}%"); }); } // 預加載統計資料 $machines = $query->orderBy("last_heartbeat_at", "desc") ->orderBy("id", "desc") ->paginate($per_page) ->withQueryString(); return view('admin.machines.index', compact('machines')); } /** * 更新機台基本資訊 (目前僅名稱) */ public function update(Request $request, Machine $machine) { $validated = $request->validate([ 'name' => 'required|string|max:255', ]); $machine->update($validated); return redirect()->route('admin.machines.index') ->with('success', __('Machine updated successfully.')); } /** * 顯示特定機台的日誌與詳細資訊 */ public function show(int $id): View { $machine = Machine::with([ 'logs' => function ($query) { $query->latest()->limit(50); } ])->findOrFail($id); return view('admin.machines.show', compact('machine')); } /** * AJAX: 取得機台抽屜面板所需的歷程日誌 */ public function logsAjax(Request $request, Machine $machine) { $per_page = $request->input('per_page', 10); $startDate = $request->get('start_date', now()->format('Y-m-d')); $endDate = $request->get('end_date', now()->format('Y-m-d')); $logs = $machine->logs() ->when($request->level, function ($query, $level) { return $query->where('level', $level); }) ->whereDate('created_at', '>=', $startDate) ->whereDate('created_at', '<=', $endDate) ->when($request->type, function ($query, $type) { return $query->where('type', $type); }) ->latest() ->paginate($per_page); return response()->json([ 'success' => true, 'data' => $logs->items(), 'pagination' => [ 'total' => $logs->total(), 'current_page' => $logs->currentPage(), 'last_page' => $logs->lastPage(), ] ]); } /** * 機台使用率統計 */ public function utilization(Request $request): View { // 取得當前使用者有權限的所有機台 (已透過 Global Scope 過濾) $machines = Machine::all(); $date = $request->get('date', now()->toDateString()); $service = app(\App\Services\Machine\MachineService::class); $fleetStats = $service->getFleetStats($date); return view('admin.machines.utilization', [ 'machines' => $machines, 'fleetStats' => $fleetStats, 'compactMachines' => $machines->map(fn($m) => [ 'id' => $m->id, 'name' => $m->name, 'serial_no' => $m->serial_no, 'status' => $m->status ])->values() ]); } /** * AJAX: 取得機台所有貨道資訊 (供效期管理視覺化圖表使用) */ public function slotsAjax(Machine $machine) { $slots = $machine->slots()->with('product:id,name,image_url')->orderByRaw('CAST(slot_no AS UNSIGNED) ASC')->get(); return response()->json([ 'success' => true, 'machine' => $machine->only(['id', 'name', 'serial_no']), 'slots' => $slots ]); } /** * AJAX: 更新貨道資訊 (庫存、效期、批號) */ public function updateSlotExpiry(Request $request, Machine $machine) { $validated = $request->validate([ 'slot_no' => 'required|integer', 'stock' => 'nullable|integer|min:0', 'expiry_date' => 'nullable|date', 'batch_no' => 'nullable|string|max:50', ]); $this->machineService->updateSlot($machine, $validated, auth()->id()); session()->flash('success', __('Slot updated successfully.')); return response()->json([ 'success' => true, 'message' => __('Slot updated successfully.') ]); } /** * 取得機台統計數據 (AJAX) */ public function utilizationData(Request $request, $id = null) { $date = $request->get('date', now()->toDateString()); $service = app(\App\Services\Machine\MachineService::class); if ($id) { $machine = Machine::findOrFail($id); $stats = $service->getUtilizationStats($machine, $date); } else { $stats = $service->getFleetStats($date); } return response()->json([ 'success' => true, 'data' => $stats ]); } /** * 機台維護紀錄 (開發中) */ public function maintenance(Request $request): View { return view('admin.machines.index', ['machines' => Machine::paginate(1)]); // Placeholder } }