diff --git a/.agents/skills/api-technical-specs/SKILL.md b/.agents/skills/api-technical-specs/SKILL.md index f281e75..0d9109a 100644 --- a/.agents/skills/api-technical-specs/SKILL.md +++ b/.agents/skills/api-technical-specs/SKILL.md @@ -41,7 +41,68 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 --- -### 3.2 B010: 心跳上報與狀態同步 +### 3.2 B005: 廣告清單同步 +用於機台端獲取目前應播放的廣告檔案 URL 清單。 + +- **URL**: `GET /api/v1/app/machine/ad/B005` +- **Request Body:** 無 (GET 請求) + +- **Response Body:** +| 參數 | 類型 | 說明 | 範例 | +| :--- | :--- | :--- | :--- | +| `success` | Boolean | 請求是否成功 | `true` | +| `code` | Integer | 內部業務狀態碼 | `200` | +| `data` | Array | 廣告物件陣列 | `[{"t070v04": "https://..."}]` | + +**data 陣列內部欄位:** +- `t070v01`: 廣告名稱 (Name) +- `t070v02`: 播放長度 (Duration) — 秒數,若後台未設定,預設為 15 秒。 +- `t070v03`: 廣告位置 (Position/Flag) — (`3`: 待機廣告, `1`: 販賣頁, `2`: 來店禮)。 +- `t070v04`: 廣告 URL。 +- `t070v05`: 播放順位 (Sort Order)。 + +--- + +### 3.3 B009: 貨道庫存即時回報 (Supplementary Report) +當維修或補貨人員在機台端完成操作後,將目前的貨道實體狀態同步回雲端。 + +#### B009 權限驗證邏輯 (RBAC Compliance) +系統會依據 `account` 欄位進行三層式權限核查: +1. **系統層 (System Admin)**:當 `company_id` 為 `null` 時,具備全局管理權限,直接放行。 +2. **公司層 (Company Admin)**:當 `is_admin` 為 `true` 時,檢查機台的 `company_id` 是否與該帳號一致。 +3. **人員層 (Operator/User)**:當帳號僅為一般人員時,檢查 `machine_user` 授權表,確認該帳號有被分配至此機台。 + +- **URL**: `PUT /api/v1/app/products/supplementary/B009` +- **Request Body:** +| 參數 | 類型 | 必填 | 說明 | 範例 | +| :--- | :--- | :--- | :--- | :--- | +| `account` | String | 是 | 操作人員帳號 | `0999123456` | +| `data` | Array | 是 | 貨道數據陣列 | `[{"tid":"1", "t060v00":"1", "num":"10"}]` | + +- **data 陣列內部欄位:** +- `tid`: 貨道編號 (Slot No) +- `t060v00`: **商品資料庫 ID** +- `num`: 實體剩餘庫存數量 + +- **Response Body (Success 200):** +| 參數 | 類型 | 說明 | 範例 | +| :--- | :--- | :--- | :--- | +| `success` | Boolean | 同步是否成功 | `true` | +| `code` | Integer | 內部業務狀態碼 | `200` | +| `message` | String | 回應訊息 | `Slot report synchronized success` | +| `status` | String | 固定回傳 `49` 代表同步完成 | `49` | + +- **Response Body (Forbidden 403):** +| 參數 | 類型 | 說明 | 範例 | +| :--- | :--- | :--- | :--- | +| `success` | Boolean | 同步失敗 | `false` | +| `status` | String | 回傳空字串 `""` 防止觸發指令 | `""` | +| `code` | Integer | HTTP 狀態碼 | `403` | +| `message` | String | 錯誤訊息 | `Unauthorized` | + +--- + +### 3.4 B010: 心跳上報與狀態同步 用於確認機台在線狀態、更新感測數據、提交事件日誌並獲取雲端指令。 - **URL**: `POST /api/v1/app/machine/status/B010` @@ -85,60 +146,3 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 - `71`: lock (鎖定) - `85`: reload B0552 (遠端出貨) - `待定義`: change (遠端找零 - 註:指令中心有此功能,但目前 Java App 尚無對接對應的連動事件) - ---- - -### 3.3 B017: 貨道與庫存同步 -- **URL**: `POST /api/v1/app/machine/reload_msg/B017` -- **說明**:當機台收到 B010 回應 `status: 49` 時,呼叫此此 API 獲取雲端最新的貨道佈局與庫存設定。 - ---- - -### 3.4 B005: 廣告清單同步 -用於機台端獲取目前應播放的廣告檔案 URL 清單。 - -- **URL**: `POST /api/v1/app/machine/ad/B005` -- **Request Body:** (無須額外 Body 參數,僅需傳送空 JSON `{}`) - -- **Response Body:** -| 參數 | 類型 | 說明 | 範例 | -| :--- | :--- | :--- | :--- | -| `success` | Boolean | 請求是否成功 | `true` | -| `data` | Array | 廣告物件陣列 | `[{"t070v04": "https://..."}]` | - -**data 陣列內部欄位:** -- `t070v01`: 廣告名稱 (Name) -- `t070v02`: 播放長度 (Duration) — 秒數,若後台未設定,預設為 15 秒。 -- `t070v03`: 廣告位置 (Position/Flag) — (`3`: 待機廣告, `1`: 販賣頁, `2`: 來店禮)。 -- `t070v04`: 廣告 URL。 -- `t070v05`: 播放順位 (Sort Order)。 - ---- - -### 3.5 B009: 貨道庫存即時回報 (Supplementary Report) -當維修或補貨人員在機台端完成操作後,將目前的貨道實體狀態同步回雲端。 - -- **URL**: `PUT /api/v1/app/products/supplementary/B009` -- **Request Body:** -| 參數 | 類型 | 必填 | 說明 | 範例 | -| :--- | :--- | :--- | :--- | :--- | -| `account` | String | 是 | 操作人員帳號 | `technician_01` | -| `vmcType` | String | 否 | VMC 韌體/機型類別 | `XinYuan` | -| `data` | Array | 貨道數據陣列 | `[{"tid":"1", "t060v00":"SKU001", "num":"10"}]` | - -- **data 陣列內部欄位:** -- `tid`: 貨道編號 (Slot No) -- `t060v00`: 商品編碼 (SKU / Product Code) -- `num`: 實體剩餘庫存數量 - -- **Response Body:** -| 參數 | 類型 | 說明 | 範例 | -| :--- | :--- | :--- | :--- | -| `success` | Boolean | 同步是否成功 | `true` | -| `status` | String | 固定回傳 `49` 代表已處理 | `49` | - ---- - -### 3.6 B600: 交易數據回傳 (規劃中) -- **URL**: `POST /api/v1/app/B600` -- 說明:交易完成後提交支付方式、金額、商品與出貨結果。 diff --git a/app/Http/Controllers/Api/V1/App/MachineController.php b/app/Http/Controllers/Api/V1/App/MachineController.php index 2231cd2..d5dfa81 100644 --- a/app/Http/Controllers/Api/V1/App/MachineController.php +++ b/app/Http/Controllers/Api/V1/App/MachineController.php @@ -5,9 +5,11 @@ namespace App\Http\Controllers\Api\V1\App; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Models\Machine\Machine; +use App\Models\System\User; use App\Jobs\Machine\ProcessHeartbeat; use App\Jobs\Machine\ProcessTimerStatus; use App\Jobs\Machine\ProcessCoinInventory; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Validator; class MachineController extends Controller @@ -104,7 +106,7 @@ class MachineController extends Controller { $machine = $request->get('machine'); $slots = $machine->slots()->with('product')->get(); - + // 自動轉 Success: 若機台來撈 B017,代表之前的 reload_stock 指令已成功被機台響應 \App\Models\Machine\RemoteCommand::where('machine_id', $machine->id) ->where('command_type', 'reload_stock') @@ -203,9 +205,11 @@ class MachineController extends Controller $machine = $request->get('machine'); $advertisements = \App\Models\Machine\MachineAdvertisement::where('machine_id', $machine->id) - ->with(['advertisement' => function ($query) { - $query->active(); - }]) + ->with([ + 'advertisement' => function ($query) { + $query->active(); + } + ]) ->get() ->filter(fn($ma) => $ma->advertisement !== null) ->map(function ($ma) { @@ -232,7 +236,7 @@ class MachineController extends Controller 't070v03' => (string) ($posIdMap[$ma->position] ?? '1'), // 位置數字改放這裡 (App 會讀這欄當 Flag) 't070v04' => $ma->advertisement->url, 't070v05' => (string) $ma->sort_order, - 'raw_pos_weight' => $posWeight[$ma->position] ?? 99, + 'raw_pos_weight' => $posWeight[$ma->position] ?? 99, 'raw_sort' => (int) $ma->sort_order ]; }) @@ -241,7 +245,7 @@ class MachineController extends Controller ['raw_sort', 'asc'] ]) ->values() - ->map(function($item) { + ->map(function ($item) { unset($item['raw_pos_weight'], $item['raw_sort']); return $item; }); @@ -260,10 +264,51 @@ class MachineController extends Controller { $machine = $request->get('machine'); $payload = $request->all(); + $account = $payload['account'] ?? null; - // 映射舊版機台回傳格式 (Map legacy machine format) - // t060v00 -> product_id, num -> stock, tid -> slot_no + // 1. 驗證帳號是否存在 (驗證執行補貨的人員身分) + $user = User::where('username', $account) + ->orWhere('email', $account) + ->first(); + + if (!$user) { + return response()->json([ + 'success' => false, + 'code' => 403, + 'message' => 'Unauthorized: Account not found', + 'status' => '' + ], 403); + } + + // 2. 階層式權限驗證 (遵循 RBAC 多租戶規範) + $isAuthorized = false; + if ($user->isSystemAdmin()) { + // [系統層]:系統管理員可異動所有機台 + $isAuthorized = true; + } elseif ($user->is_admin) { + // [公司層]:公司管理員需驗證此機台是否隸屬於該公司 + $isAuthorized = ($machine->company_id === $user->company_id); + } else { + // [人員層]:一般人員需檢查 machine_user 授權表 + $isAuthorized = $user->machines()->where('machine_id', $machine->id)->exists(); + } + + if (!$isAuthorized) { + return response()->json([ + 'success' => false, + 'code' => 403, + 'message' => 'Unauthorized: Account not authorized for this machine', + 'status' => '' + ], 403); + } + + // 3. 映射舊版機台回傳格式 (Map legacy machine format) + // 支持單個物件 data: {} 或 陣列 data: [{}] (Handle both single object and array) $legacyData = $payload['data'] ?? []; + if (Arr::isAssoc($legacyData)) { + $legacyData = [$legacyData]; + } + $mappedSlots = array_map(function ($item) { return [ 'slot_no' => $item['tid'] ?? null, diff --git a/app/Models/Product/Product.php b/app/Models/Product/Product.php index ffb365d..1267c43 100644 --- a/app/Models/Product/Product.php +++ b/app/Models/Product/Product.php @@ -16,7 +16,6 @@ class Product extends Model 'category_id', 'name', 'name_dictionary_key', - 'sku', 'barcode', 'spec', 'manufacturer', diff --git a/app/Models/Transaction/OrderItem.php b/app/Models/Transaction/OrderItem.php index f7858c3..2562aed 100644 --- a/app/Models/Transaction/OrderItem.php +++ b/app/Models/Transaction/OrderItem.php @@ -14,7 +14,7 @@ class OrderItem extends Model 'order_id', 'product_id', 'product_name', - 'sku', + 'barcode', 'price', 'quantity', 'subtotal', diff --git a/app/Services/Machine/MachineService.php b/app/Services/Machine/MachineService.php index ffba6ae..933ec61 100644 --- a/app/Services/Machine/MachineService.php +++ b/app/Services/Machine/MachineService.php @@ -67,11 +67,10 @@ class MachineService // 蒐集所有傳入的商品 ID (可能是 SKU 或 實際 ID) $productCodes = collect($slotsData)->pluck('product_id')->filter()->unique()->toArray(); - // 批次查詢商品 (支援以 SKU 查詢,確保對應至資料庫 ID) - $products = \App\Models\Product\Product::whereIn('sku', $productCodes) - ->orWhereIn('id', $productCodes) - ->get() - ->keyBy(fn($p) => $p->sku ?: $p->id); + // 優先以 ID 查詢商品,若 ID 不存在則嘗試 Barcode (Prioritize ID lookup, fallback to Barcode) + $products = \App\Models\Product\Product::whereIn('id', $productCodes) + ->orWhereIn('barcode', $productCodes) + ->get(); foreach ($slotsData as $slotData) { $slotNo = $slotData['slot_no'] ?? null; @@ -79,11 +78,13 @@ class MachineService $existingSlot = $machine->slots()->where('slot_no', $slotNo)->first(); - // 查找對應的實體 ID + // 查找對應的實體 ID (支援 ID 與 Barcode 比對) $productCode = $slotData['product_id'] ?? null; $actualProductId = null; if ($productCode) { - $actualProductId = $products->get($productCode)?->id; + $actualProductId = $products->first(function ($p) use ($productCode) { + return (string)$p->id === (string)$productCode || $p->barcode === (string)$productCode; + })?->id; } $updateData = [ diff --git a/app/Services/Transaction/TransactionService.php b/app/Services/Transaction/TransactionService.php index 5816043..206fa70 100644 --- a/app/Services/Transaction/TransactionService.php +++ b/app/Services/Transaction/TransactionService.php @@ -42,7 +42,7 @@ class TransactionService $order->items()->create([ 'product_id' => $item['product_id'], 'product_name' => $item['product_name'] ?? 'Unknown', - 'sku' => $item['sku'] ?? null, + 'barcode' => $item['barcode'] ?? null, 'price' => $item['price'], 'quantity' => $item['quantity'], 'subtotal' => $item['price'] * $item['quantity'], diff --git a/config/api-docs.php b/config/api-docs.php index 0564612..4667378 100644 --- a/config/api-docs.php +++ b/config/api-docs.php @@ -8,6 +8,119 @@ return [ [ 'name' => '機台核心通訊 (IoT Core)', 'apis' => [ + [ + 'name' => 'B005: 廣告清單同步 (Ad Sync)', + 'slug' => 'b005-ad-sync', + 'method' => 'GET', + 'path' => '/api/v1/app/machine/ad/B005', + 'description' => '用於機台端獲取目前應播放的廣告檔案 URL 清單。此介面無需 Request Body。', + 'headers' => [ + 'Authorization' => 'Bearer ', + 'Content-Type' => 'application/json', + ], + 'parameters' => [], + 'response_parameters' => [ + 'success' => [ + 'type' => 'boolean', + 'description' => '請求是否成功', + 'example' => true + ], + 'code' => [ + 'type' => 'integer', + 'description' => '內部業務狀態碼', + 'example' => 200 + ], + 'data' => [ + 'type' => 'array', + 'description' => '廣告物件陣列。內部欄位包含:t070v01 (名稱), t070v02 (秒數), t070v03 (位置:1:販賣頁, 2:來店禮, 3:待機廣告), t070v04 (URL), t070v05 (順位)', + 'example' => [ + [ + 't070v01' => '測試機台廣告', + 't070v02' => 15, + 't070v03' => 3, + 't070v04' => 'https://example.com/ad1.mp4', + 't070v05' => 1 + ] + ] + ], + ], + 'request' => [], + 'response' => [ + 'success' => true, + 'code' => 200, + 'message' => 'OK', + 'data' => [ + [ + 't070v01' => '測試機台廣告', + 't070v02' => 15, + 't070v03' => 3, + 't070v04' => 'https://example.com/ad1.mp4', + 't070v05' => 1 + ] + ] + ], + ], + [ + 'name' => 'B009: 貨道庫存即時回報 (Inventory Report)', + 'slug' => 'b009-inventory-report', + 'method' => 'PUT', + 'path' => '/api/v1/app/products/supplementary/B009', + 'description' => '當人員在機台端完成操作後,將目前的貨道實體狀態同步回雲端。需進行 RBAC 權限核查。', + 'headers' => [ + 'Authorization' => 'Bearer ', + 'Content-Type' => 'application/json', + ], + 'parameters' => [ + 'account' => [ + 'type' => 'string', + 'required' => true, + 'description' => '操作人員帳號', + 'example' => '0999123456' + ], + 'data' => [ + 'type' => 'array', + 'required' => true, + 'description' => '貨道數據陣列。tid: 貨道號, t060v00: 商品 ID, num: 庫存量', + 'example' => [ + ['tid' => '1', 't060v00' => '1', 'num' => '10'] + ] + ], + ], + 'response_parameters' => [ + 'success' => [ + 'type' => 'boolean', + 'description' => '同步是否成功', + 'example' => true + ], + 'code' => [ + 'type' => 'integer', + 'description' => '內部業務狀態碼', + 'example' => 200 + ], + 'message' => [ + 'type' => 'string', + 'description' => '回應訊息', + 'example' => 'Slot report synchronized success' + ], + 'status' => [ + 'type' => 'string', + 'description' => '固定回傳 49 代表同步完成', + 'example' => '49' + ], + ], + 'request' => [ + 'account' => '0999123456', + 'data' => [ + ['tid' => '1', 't060v00' => '1', 'num' => '10'] + ] + ], + 'response' => [ + 'success' => true, + 'code' => 200, + 'message' => 'Slot report synchronized success', + 'status' => '49' + ], + ], [ 'name' => 'B010: 心跳上報與狀態同步 (Heartbeat)', 'slug' => 'b010-heartbeat', diff --git a/database/migrations/2026_04_07_134000_remove_sku_and_sync_barcode.php b/database/migrations/2026_04_07_134000_remove_sku_and_sync_barcode.php new file mode 100644 index 0000000..ad90910 --- /dev/null +++ b/database/migrations/2026_04_07_134000_remove_sku_and_sync_barcode.php @@ -0,0 +1,45 @@ +index('company_id'); + // 現在可以安全移除含有 sku 的索引了 + $table->dropIndex(['company_id', 'sku']); + $table->dropColumn('sku'); + }); + + // 2. 從 order_items 表移除 sku 並新增 barcode + Schema::table('order_items', function (Blueprint $table) { + $table->dropColumn('sku'); + $table->string('barcode')->nullable()->after('product_name')->comment('商品條碼 (備份)'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('order_items', function (Blueprint $table) { + $table->dropColumn('barcode'); + $table->string('sku')->nullable()->after('product_name')->comment('商品編號 (備份)'); + }); + + Schema::table('products', function (Blueprint $table) { + $table->string('sku')->nullable()->after('name_dictionary_key')->comment('商品編號'); + $table->index(['company_id', 'sku']); + }); + } +}; diff --git a/lang/en.json b/lang/en.json index c8c3cda..c3165c8 100644 --- a/lang/en.json +++ b/lang/en.json @@ -615,6 +615,7 @@ "No roles available": "No roles available", "No roles found.": "No roles found.", "No slots found": "No slots found", + "No slot data available": "No slot data available", "No users found": "No users found", "None": "None", "Normal": "Normal", @@ -904,6 +905,7 @@ "Stock": "Stock", "Stock & Expiry": "Stock & Expiry", "Stock & Expiry Management": "Stock & Expiry Management", + "Stock & Expiry Overview": "Stock & Expiry Overview", "Stock Management": "Stock Management", "Stock Quantity": "Stock Quantity", "Stock:": "Stock:", @@ -1025,6 +1027,7 @@ "Venue Management": "Venue Management", "video": "video", "View Details": "View Details", + "View Inventory": "View Inventory", "View Logs": "View Logs", "View More": "View More", "Visit Gift": "Visit Gift", diff --git a/lang/ja.json b/lang/ja.json index c9a7110..57aa852 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -615,6 +615,7 @@ "No roles available": "利用可能な権限はありません", "No roles found.": "権限が見つかりません。", "No slots found": "スロットが見つかりません", + "No slot data available": "スロットデータがありません", "No users found": "ユーザーが見つかりません", "None": "なし", "Normal": "通常", @@ -904,6 +905,7 @@ "Stock": "在庫", "Stock & Expiry": "在庫と消費期限", "Stock & Expiry Management": "在庫・期限管理", + "Stock & Expiry Overview": "在庫・期限一覧", "Stock Management": "在庫管理", "Stock Quantity": "在庫数", "Stock:": "在庫:", @@ -1025,6 +1027,7 @@ "Venue Management": "会場管理", "video": "video", "View Details": "詳細を見る", + "View Inventory": "在庫を見る", "View Logs": "ログを見る", "View More": "もっと見る", "Visit Gift": "来店ギフト", diff --git a/lang/zh_TW.json b/lang/zh_TW.json index 850cd97..2e4f41f 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -615,6 +615,7 @@ "No roles available": "目前沒有角色資料。", "No roles found.": "找不到角色資料。", "No slots found": "未找到貨道資訊", + "No slot data available": "尚無貨道資料", "No users found": "找不到用戶資料", "None": "無", "Normal": "正常", @@ -904,6 +905,7 @@ "Stock": "庫存", "Stock & Expiry": "庫存與效期", "Stock & Expiry Management": "庫存與效期管理", + "Stock & Expiry Overview": "庫存與效期一覽", "Stock Management": "庫存管理單", "Stock Quantity": "庫存數量", "Stock:": "庫存:", @@ -1025,6 +1027,7 @@ "Venue Management": "場地管理", "video": "影片", "View Details": "查看詳情", + "View Inventory": "查看庫存", "View Logs": "查看日誌", "View More": "查看更多", "Visit Gift": "來店禮", diff --git a/resources/views/admin/machines/index.blade.php b/resources/views/admin/machines/index.blade.php index 3987d11..40d5cec 100644 --- a/resources/views/admin/machines/index.blade.php +++ b/resources/views/admin/machines/index.blade.php @@ -7,6 +7,7 @@ return { showLogPanel: false, showEditModal: false, + showInventoryPanel: false, editMachineId: '', editMachineName: '', activeTab: 'status', @@ -15,12 +16,14 @@ currentMachineName: '', logs: [], loading: false, + inventoryLoading: false, startDate: '', endDate: '', tab: 'list', viewMode: 'fleet', selectedMachine: null, slots: [], + inventorySlots: [], init() { const d = new Date(); @@ -79,11 +82,43 @@ finally { this.loading = false; } }, + // 庫存一覽面板 (唯讀) + async openInventoryPanel(id, sn, name) { + this.currentMachineId = id; + this.currentMachineSn = sn; + this.currentMachineName = name; + this.inventorySlots = []; + this.showInventoryPanel = true; + this.inventoryLoading = true; + try { + const res = await fetch('/admin/machines/' + id + '/slots-ajax'); + const data = await res.json(); + if (data.success) { + this.inventorySlots = data.slots; + } + } catch (e) { console.error('openInventoryPanel error:', e); } + finally { this.inventoryLoading = false; } + }, + + getSlotColorClass(slot) { + if (!slot.expiry_date) return 'bg-slate-50/50 dark:bg-slate-800/50 text-slate-400 border-slate-200/60 dark:border-slate-700/50'; + const todayStr = new Date().toISOString().split('T')[0]; + const expiryStr = slot.expiry_date; + if (expiryStr < todayStr) { + return 'bg-rose-50/60 dark:bg-rose-500/10 text-rose-600 dark:text-rose-400 border-rose-200 dark:border-rose-500/30 shadow-sm shadow-rose-500/5'; + } + const diffDays = Math.round((new Date(expiryStr) - new Date(todayStr)) / 86400000); + if (diffDays <= 7) { + return 'bg-amber-50/60 dark:bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-200 dark:border-amber-500/30 shadow-sm shadow-amber-500/5'; + } + return 'bg-emerald-50/60 dark:bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-200 dark:border-emerald-500/30 shadow-sm shadow-emerald-500/5'; + }, + }; }; -
+
@@ -243,6 +278,16 @@
+
@@ -571,4 +618,194 @@
+ + + @endsection \ No newline at end of file diff --git a/resources/views/docs/api-docs.blade.php b/resources/views/docs/api-docs.blade.php index 1891380..162b4ae 100644 --- a/resources/views/docs/api-docs.blade.php +++ b/resources/views/docs/api-docs.blade.php @@ -166,7 +166,12 @@ - {{ $api['name'] }} +
+ + {{ $api['method'] }} + + {{ $api['name'] }} +
@endforeach @endforeach @@ -187,7 +192,12 @@
-

{{ $api['name'] }}

+
+ + {{ $api['method'] }} + +

{{ $api['name'] }}

+

{{ $api['description'] }}

@@ -264,7 +274,7 @@ 範例: {{ is_array($param['example']) ? json_encode($param['example']) : $param['example'] }} + class="text-sm text-cyan-600 font-bold">{{ is_array($param['example']) ? json_encode($param['example'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $param['example'] }}
@endif @@ -280,7 +290,7 @@

請求範例 (Request Body)

-
{{ json_encode($api['request'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
+
{{ json_encode($api['request'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) }}
@@ -310,7 +320,7 @@ @if(isset($param['example']))
範例: - {{ $param['example'] }} + {{ is_array($param['example']) ? json_encode($param['example'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $param['example'] }}
@endif @@ -322,7 +332,7 @@ @endif

回應範例 (Response Body)

-
{{ json_encode($api['response'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
+
{{ json_encode($api['response'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) }}
@if(isset($api['notes'])) diff --git a/routes/api.php b/routes/api.php index 31371c1..0d11ad2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -62,7 +62,7 @@ Route::prefix('v1')->middleware(['throttle:api'])->group(function () { Route::post('machine/member/verify/B650', [App\Http\Controllers\Api\V1\App\MachineController::class, 'verifyMember']); // 廣告與貨道清單 (B005, B009) - Route::post('machine/ad/B005', [App\Http\Controllers\Api\V1\App\MachineController::class, 'getAdvertisements']); + Route::get('machine/ad/B005', [App\Http\Controllers\Api\V1\App\MachineController::class, 'getAdvertisements']); Route::put('products/supplementary/B009', [App\Http\Controllers\Api\V1\App\MachineController::class, 'reportSlotList']); // 交易、發票與出貨 (B600, B601, B602)