All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 1m7s
1. 新增廣告管理列表與機台配置介面,包含多語系 (zh_TW, en, ja) 與完整 CRUD 2. 實作基於 Alpine 的廣告素材預覽輪播功能 3. 優化廣告素材下拉選單,強制綁定所屬公司以達成多租戶資料隔離 4. 重構廣告配置中廣告影片的縮圖渲染邏輯,移除 <video> 標籤以大幅提升頁面載入速度與節省頻寬 5. 放寬個人檔案頭像上傳限制,支援 WebP 格式
222 lines
7.0 KiB
PHP
222 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Models\Machine\Machine;
|
|
use App\Models\Machine\MachineAdvertisement;
|
|
use App\Models\System\Advertisement;
|
|
use App\Models\System\Company;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class AdvertisementController extends AdminController
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$user = auth()->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:5120' : 'max:51200', // Image 5MB, Video 50MB
|
|
],
|
|
'company_id' => 'nullable|exists:companies,id',
|
|
]);
|
|
|
|
$user = auth()->user();
|
|
$path = $request->file('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,
|
|
]);
|
|
|
|
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:5120' : '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')) {
|
|
// 刪除舊檔案
|
|
$oldPath = str_replace(Storage::disk('public')->url(''), '', $advertisement->url);
|
|
Storage::disk('public')->delete($oldPath);
|
|
|
|
// 存入新檔案
|
|
$path = $request->file('file')->store('ads', 'public');
|
|
$data['url'] = Storage::disk('public')->url($path);
|
|
}
|
|
|
|
$advertisement->update($data);
|
|
|
|
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();
|
|
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.')
|
|
]);
|
|
}
|
|
}
|