user(); $tab = $request->input('tab', 'list'); // Tab 1: 廣告列表 $advertisements = Advertisement::with('company')->latest()->paginate(10); $allAds = Advertisement::active()->get(); // Tab 2: 機台廣告設置 (所需資料) // 取得使用者有權限的機台列表 (已透過 Global Scope 過濾) $machines = Machine::select('id', 'name', 'serial_no', 'company_id')->get(); $companies = $user->isSystemAdmin() ? Company::orderBy('name')->get() : collect(); return view('admin.ads.index', [ 'advertisements' => $advertisements, 'machines' => $machines, 'tab' => $tab, 'allAds' => $allAds, 'companies' => $companies, ]); } /** * 素材 CRUD: 儲存廣告 */ public function store(Request $request) { $request->validate([ 'name' => 'required|string|max:255', 'type' => 'required|in:image,video', 'duration' => 'required|in:15,30,60', 'file' => [ 'required', 'file', 'mimes:jpeg,png,jpg,gif,webp,mp4,mov,avi', $request->type === 'image' ? 'max:10240' : 'max:51200', // Image 10MB, Video 50MB ], 'company_id' => 'nullable|exists:companies,id', ]); $user = auth()->user(); $file = $request->file('file'); if ($request->type === 'image') { $path = $this->storeAsWebp($file, 'ads'); } else { $path = $file->store('ads', 'public'); } if ($user->isSystemAdmin()) { $companyId = $request->filled('company_id') ? $request->company_id : null; } else { $companyId = $user->company_id; } Advertisement::create([ 'company_id' => $companyId, 'name' => $request->name, 'type' => $request->type, 'duration' => (int) $request->duration, 'url' => Storage::disk('public')->url($path), 'is_active' => true, ]); if ($request->wantsJson()) { return response()->json([ 'success' => true, 'message' => __('Advertisement created successfully.'), 'data' => $advertisement ]); } return redirect()->back()->with('success', __('Advertisement created successfully.')); } public function update(Request $request, Advertisement $advertisement) { $rules = [ 'name' => 'required|string|max:255', 'type' => 'required|in:image,video', 'duration' => 'required|in:15,30,60', 'is_active' => 'boolean', 'company_id' => 'nullable|exists:companies,id', ]; if ($request->hasFile('file')) { $rules['file'] = [ 'file', 'mimes:jpeg,png,jpg,gif,webp,mp4,mov,avi', $request->type === 'image' ? 'max:10240' : 'max:51200', ]; } $request->validate($rules); $data = $request->only(['name', 'type', 'duration']); $data['is_active'] = $request->has('is_active'); $user = auth()->user(); if ($user->isSystemAdmin()) { $data['company_id'] = $request->filled('company_id') ? $request->company_id : null; } if ($request->hasFile('file')) { // 刪除舊檔案 // 處理 URL 可能包含 storage 或原始路徑的情況 $oldPath = str_replace(Storage::disk('public')->url(''), '', $advertisement->url); // 去除開頭可能的斜線 $oldPath = ltrim($oldPath, '/'); Storage::disk('public')->delete($oldPath); // 存入新檔案 $file = $request->file('file'); if ($request->type === 'image') { $path = $this->storeAsWebp($file, 'ads'); } else { $path = $file->store('ads', 'public'); } $data['url'] = Storage::disk('public')->url($path); } $advertisement->update($data); if ($request->wantsJson()) { return response()->json([ 'success' => true, 'message' => __('Advertisement updated successfully.'), 'data' => $advertisement ]); } return redirect()->back()->with('success', __('Advertisement updated successfully.')); } public function destroy(Advertisement $advertisement) { // 檢查是否有機台正投放中 if ($advertisement->machineAdvertisements()->exists()) { return redirect()->back()->with('error', __('Cannot delete advertisement being used by machines.')); } // 刪除實體檔案 $path = str_replace(Storage::disk('public')->url(''), '', $advertisement->url); Storage::disk('public')->delete($path); $advertisement->delete(); if ($request->wantsJson()) { return response()->json([ 'success' => true, 'message' => __('Advertisement deleted successfully.') ]); } return redirect()->back()->with('success', __('Advertisement deleted successfully.')); } /** * AJAX: 取得特定機台的廣告投放清單 */ public function getMachineAds(Machine $machine) { $assignments = MachineAdvertisement::where('machine_id', $machine->id) ->with('advertisement') ->get() ->groupBy('position'); return response()->json([ 'success' => true, 'data' => $assignments ]); } /** * 投放廣告至機台 */ public function assign(Request $request) { $request->validate([ 'machine_id' => 'required|exists:machines,id', 'advertisement_id' => 'required|exists:advertisements,id', 'position' => 'required|in:vending,visit_gift,standby', 'sort_order' => 'nullable|integer', ]); // If sort_order is not provided, append to the end of the current position list $newSortOrder = $request->sort_order; if (is_null($newSortOrder)) { $newSortOrder = MachineAdvertisement::where('machine_id', $request->machine_id) ->where('position', $request->position) ->max('sort_order') + 1; } MachineAdvertisement::updateOrCreate( [ 'machine_id' => $request->machine_id, 'position' => $request->position, 'advertisement_id' => $request->advertisement_id, ], [ 'sort_order' => $newSortOrder, ] ); return response()->json([ 'success' => true, 'message' => __('Advertisement assigned successfully.') ]); } /** * 重新排序廣告播放順序 */ public function reorderAssignments(Request $request) { $request->validate([ 'assignment_ids' => 'required|array', 'assignment_ids.*' => 'exists:machine_advertisements,id' ]); foreach ($request->assignment_ids as $index => $id) { MachineAdvertisement::where('id', $id)->update(['sort_order' => $index]); } return response()->json([ 'success' => true, 'message' => __('Order updated successfully.') ]); } /** * 移除廣告投放 */ public function removeAssignment($id) { $assignment = MachineAdvertisement::findOrFail($id); $assignment->delete(); return response()->json([ 'success' => true, 'message' => __('Assignment removed successfully.') ]); } }