All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 1m7s
1. 修改 MachineController@getAdvertisements 回傳欄位,將 t070v02 改為播放秒數,t070v03 改為位置代碼 (Flag)。 2. 根據 Android App 原始碼分析結果,調整位置對應:3 為待機廣告 (HomeActivity),1 為販賣頁廣告 (FontendActivity)。 3. 在 AdvertisementController@getMachineAds 增加 sort_order 排序,確保後台管理介面視圖與 API 輸出順序一致。 4. 更新廣告下載 API 的技術文件 (SKILL.md),明確標記欄位用途與位置代碼。 5. 在 routes/api.php 補上 B005 與 B009 的路由定義。
263 lines
8.2 KiB
PHP
263 lines
8.2 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 App\Traits\ImageHandler;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class AdvertisementController extends AdminController
|
|
{
|
|
use ImageHandler;
|
|
|
|
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: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')
|
|
->orderBy('sort_order', 'asc')
|
|
->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.')
|
|
]);
|
|
}
|
|
}
|