From 284d56a544c4fc64976958469e2f024aaa7cec7e Mon Sep 17 00:00:00 2001 From: sky121113 Date: Mon, 11 May 2026 11:01:48 +0800 Subject: [PATCH] =?UTF-8?q?[REFACTOR]=20=E6=94=AF=E4=BB=98=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E5=A4=9A=E8=AA=9E=E7=B3=BB=E5=8C=96=E8=88=87=20UI=20?= =?UTF-8?q?=E9=9F=BF=E6=87=89=E5=BC=8F=E5=84=AA=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. [REFACTOR] Order 模型:將支付類型標籤改為多語系轉譯,支援繁中、英、日。 2. [FEAT] 補全 lang/*.json 中的支付類型翻譯。 3. [STYLE] layouts/admin.blade.php:優化電腦版與手機版邊距佈局。 4. [STYLE] 銷售紀錄分頁:優化手機版 info grid 響應式顯示。 5. [FIX] 銷售紀錄:恢復手機版完整日期時間格式。 6. [DELETE] 移除 B710 (Timer Sync) 冗餘代碼與路由。 7. [DOCS] 更新 API 文件配置。 --- .../Api/V1/App/MachineController.php | 13 - app/Jobs/Machine/ProcessTimerStatus.php | 51 --- app/Models/Machine/TimerStatus.php | 28 -- app/Models/Transaction/Order.php | 6 +- config/api-docs.php | 16 - lang/en.json | 30 ++ lang/ja.json | 35 +- lang/zh_TW.json | 39 +- .../sales/partials/tab-dispense.blade.php | 345 ++++++++-------- .../sales/partials/tab-invoices.blade.php | 371 ++++++++++-------- .../admin/sales/partials/tab-orders.blade.php | 4 +- resources/views/layouts/admin.blade.php | 45 ++- routes/api.php | 1 - 13 files changed, 510 insertions(+), 474 deletions(-) delete mode 100644 app/Jobs/Machine/ProcessTimerStatus.php delete mode 100644 app/Models/Machine/TimerStatus.php diff --git a/app/Http/Controllers/Api/V1/App/MachineController.php b/app/Http/Controllers/Api/V1/App/MachineController.php index 1990c24..5c237ae 100644 --- a/app/Http/Controllers/Api/V1/App/MachineController.php +++ b/app/Http/Controllers/Api/V1/App/MachineController.php @@ -7,7 +7,6 @@ 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 App\Jobs\Machine\ProcessMachineError; use App\Jobs\Machine\ProcessStateLog; @@ -197,18 +196,6 @@ class MachineController extends Controller } - /** - * B710: Sync Timer status (Asynchronous) - */ - public function syncTimer(Request $request) - { - $machine = $request->get('machine'); - $data = $request->except(['machine', 'key']); // 排除 Middleware 注入物件 - - ProcessTimerStatus::dispatch($machine->serial_no, $data); - - return response()->json(['success' => true], 202); - } /** * B220: Sync Coin Inventory (Asynchronous) diff --git a/app/Jobs/Machine/ProcessTimerStatus.php b/app/Jobs/Machine/ProcessTimerStatus.php deleted file mode 100644 index 77f0753..0000000 --- a/app/Jobs/Machine/ProcessTimerStatus.php +++ /dev/null @@ -1,51 +0,0 @@ -serialNo = $serialNo; - $this->data = $data; - } - - /** - * Execute the job. - */ - public function handle(): void - { - try { - $machine = Machine::where('serial_no', $this->serialNo)->firstOrFail(); - - TimerStatus::updateOrCreate( - ['machine_id' => $machine->id, 'slot_no' => $this->data['slot_no']], - [ - 'status' => $this->data['status'], - 'remaining_seconds' => $this->data['remaining_seconds'], - 'end_at' => isset($this->data['end_at']) ? \Carbon\Carbon::parse($this->data['end_at']) : null, - ] - ); - } catch (\Exception $e) { - Log::error("Failed to process timer status for machine {$this->serialNo}: " . $e->getMessage()); - throw $e; - } - } -} diff --git a/app/Models/Machine/TimerStatus.php b/app/Models/Machine/TimerStatus.php deleted file mode 100644 index ff43100..0000000 --- a/app/Models/Machine/TimerStatus.php +++ /dev/null @@ -1,28 +0,0 @@ - 'datetime', - ]; - - public function machine() - { - return $this->belongsTo(Machine::class); - } -} diff --git a/app/Models/Transaction/Order.php b/app/Models/Transaction/Order.php index 740745d..7e0379f 100644 --- a/app/Models/Transaction/Order.php +++ b/app/Models/Transaction/Order.php @@ -74,11 +74,11 @@ class Order extends Model 23 => __('Offline + 3'), 24 => __('Offline + 4'), 25 => __('Offline + 9'), - 30 => 'LINE Pay', + 30 => __('LINE Pay'), 31 => __('JKO Pay'), 32 => __('Easy Wallet'), - 33 => 'Pi Pay', - 34 => 'PlusPay', + 33 => __('Pi Pay'), + 34 => __('PlusPay'), 40 => __('Member Verify Pickup'), 41 => __('Staff Card'), 50 => __('Offline + LINE Pay'), diff --git a/config/api-docs.php b/config/api-docs.php index c5e932c..857a0ff 100644 --- a/config/api-docs.php +++ b/config/api-docs.php @@ -409,22 +409,6 @@ return [ ], 'notes' => '驗證成功後會建立刷卡日誌。連續錯誤同樣會觸發鎖定。' ], - [ - 'name' => 'B710: 機台時間同步 (Timer Sync)', - 'slug' => 'b710-timer-sync', - 'method' => 'POST', - 'path' => '/api/v1/app/machine/timer/B710', - 'description' => '校準機台 RTC 時間。', - 'headers' => [ - 'Authorization' => 'Bearer ', - ], - 'response' => [ - 'success' => true, - 'data' => [ - 'timestamp' => 1714444800 - ] - ] - ], [ 'name' => 'B027: 贈品碼/優惠券驗證 (Free Gift Verify)', 'slug' => 'b027-freebie-code', diff --git a/lang/en.json b/lang/en.json index fac06a0..6aa971b 100644 --- a/lang/en.json +++ b/lang/en.json @@ -200,6 +200,17 @@ "Cancel Code": "Cancel Code", "Cancel Order": "Cancel Order", "Cancel Pass Code": "Cancel Pass Code", + "Offline + 1": "Offline + 1", + "Offline + 2": "Offline + 2", + "Offline + 3": "Offline + 3", + "Offline + 4": "Offline + 4", + "Offline + 9": "Offline + 9", + "Offline + LINE Pay": "Offline + LINE Pay", + "Offline + JKO Pay": "Offline + JKO Pay", + "Offline + Easy Wallet": "Offline + Easy Wallet", + "Offline + Pi Pay": "Offline + Pi Pay", + "Offline + PlusPay": "Offline + PlusPay", + "Points/Voucher": "Points/Voucher", "Cancel Pickup Code": "Cancel Pickup Code", "Cancel Purchase": "Cancel Purchase", "Cancelled": "Cancelled", @@ -625,6 +636,9 @@ "LINE Pay Direct": "LINE Pay Direct", "LINE Pay Direct Settings Description": "LINE Pay Official Direct Connection Settings", "LINE_MERCHANT_ID": "LINE_MERCHANT_ID", + "LINE Pay": "LINE Pay", + "Pi Pay": "Pi Pay", + "PlusPay": "PlusPay", "LIVE": "LIVE", "Last Communication": "Last Communication", "Last Heartbeat": "Last Heartbeat", @@ -779,9 +793,24 @@ "Member": "Member", "Member & External": "Member & External", "Member List": "Member List", + "Member + 1": "Member + 1", + "Member + 2": "Member + 2", + "Member + 3": "Member + 3", + "Member + 4": "Member + 4", + "Member + 5": "Member + 5", + "Member + 6": "Member + 6", + "Member + 7": "Member + 7", + "Member + 8": "Member + 8", + "Member + 9": "Member + 9", + "Member + LINE Pay": "Member + LINE Pay", + "Member + JKO Pay": "Member + JKO Pay", + "Member + Easy Wallet": "Member + Easy Wallet", + "Member + Pi Pay": "Member + Pi Pay", + "Member + PlusPay": "Member + PlusPay", "Member Management": "Member Management", "Member Price": "Member Price", "Member Status": "Member Status", + "Member Verify Pickup": "Member Verify Pickup", "Member System": "Member System", "Membership Tiers": "Membership Tiers", "Menu Permissions": "Menu Permissions", @@ -1329,6 +1358,7 @@ "Spring": "Spring", "Spring Channel Limit": "Spring Channel Limit", "Spring Limit": "Spring Limit", + "Staff Card": "Staff Card", "Staff Stock": "Staff Stock", "Standby": "Standby", "Standby Ad": "Standby Ad", diff --git a/lang/ja.json b/lang/ja.json index 9224c6a..b28b12f 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -200,6 +200,17 @@ "Cancel Order": "注文取消", "Cancel Pass Code": "通行コードをキャンセル", "Cancel Pickup Code": "受取コードをキャンセル", + "Offline + 1": "オフライン + 1", + "Offline + 2": "オフライン + 2", + "Offline + 3": "オフライン + 3", + "Offline + 4": "オフライン + 4", + "Offline + 9": "オフライン + 9", + "Offline + LINE Pay": "オフライン + LINE Pay", + "Offline + JKO Pay": "オフライン + JKO Pay", + "Offline + Easy Wallet": "オフライン + Easy Wallet", + "Offline + Pi Pay": "オフライン + Pi Pay", + "Offline + PlusPay": "オフライン + PlusPay", + "Points/Voucher": "ポイント/クーポン", "Cancel Purchase": "Cancel Purchase", "Cancelled": "キャンセル済み", "Cannot Delete Role": "Cannot Delete Role", @@ -228,6 +239,8 @@ "Category Name (en)": "Category Name (en)", "Category Name (ja)": "Category Name (ja)", "Category Name (zh_TW)": "Category Name (zh_TW)", + "E-Ticket (EasyCard/iPass)": "電子マネー (悠遊カード/iPass)", + "Easy Wallet": "悠遊付 (Easy Wallet)", "Change": "Change", "Change Note": "Change Note", "Change Stock": "Change Stock", @@ -250,6 +263,7 @@ "Code Copied": "Code Copied", "Coin/Banknote Machine": "硬貨/紙幣モジュール", "Coin/Bill Acceptor": "コイン/紙幣機", + "Coin Acceptor": "硬貨識別機", "Command Center": "Command Center", "Command Confirmation": "Command Confirmation", "Command Type": "Command Type", @@ -621,7 +635,10 @@ "LINE Pay Direct": "LINE Pay Direct", "LINE Pay Direct Settings Description": "LINE Pay Direct Settings Description", "LINE_MERCHANT_ID": "LINE_MERCHANT_ID", - "LIVE": "LIVE", + "LINE Pay": "LINE Pay", + "Pi Pay": "Pi Pay", + "PlusPay": "PlusPay", + "Inactive": "Inactive", "Last Communication": "Last Communication", "Last Heartbeat": "Last Heartbeat", "Last Page": "Last Page", @@ -769,12 +786,27 @@ "Max Capacity": "最大容量", "Max Capacity:": "Max Capacity:", "Max Stock": "最大在庫", + "Member + 1": "会員 + 1", + "Member + 2": "会員 + 2", + "Member + 3": "会員 + 3", + "Member + 4": "会員 + 4", + "Member + 5": "会員 + 5", + "Member + 6": "会員 + 6", + "Member + 7": "会員 + 7", + "Member + 8": "会員 + 8", + "Member + 9": "会員 + 9", + "Member + LINE Pay": "会員 + LINE Pay", + "Member + JKO Pay": "会員 + 街口支付", + "Member + Easy Wallet": "会員 + 悠遊付", + "Member + Pi Pay": "会員 + Pi 拍錢包", + "Member + PlusPay": "会員 + 全盈+PAY", "Member": "Member", "Member & External": "Member & External", "Member List": "Member List", "Member Management": "Member Management", "Member Price": "Member Price", "Member Status": "Member Status", + "Member Verify Pickup": "会員認証受取", "Member System": "Member System", "Membership Tiers": "Membership Tiers", "Menu Permissions": "Menu Permissions", @@ -1323,6 +1355,7 @@ "Spring": "スプリング", "Spring Channel Limit": "Spring Channel Limit", "Spring Limit": "Spring Limit", + "Staff Card": "スタッフカード", "Staff Stock": "Staff Stock", "Standby": "Standby", "Standby Ad": "Standby Ad", diff --git a/lang/zh_TW.json b/lang/zh_TW.json index f6d3aca..dd3b23d 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -81,6 +81,7 @@ "Advertisement deleted successfully.": "廣告刪除成功。", "Advertisement updated successfully": "廣告更新成功", "Advertisement updated successfully.": "廣告更新成功。", + "Bill Acceptor": "紙鈔機", "Affiliated Company": "所屬公司", "Affiliated Unit": "公司名稱", "Affiliation": "所屬單位", @@ -257,6 +258,7 @@ "Code Copied": "代碼已複製", "Coin/Banknote Machine": "硬幣機/紙鈔機", "Coin/Bill Acceptor": "硬幣機/紙鈔機", + "Coin Acceptor": "硬幣機", "Command Center": "指令中心", "Command Confirmation": "指令確認", "Command Type": "指令類型", @@ -470,6 +472,8 @@ "Edit Staff Card": "編輯員工識別卡", "Edit Sub Account Role": "編輯子帳號角色", "Edit Warehouse": "編輯倉庫", + "E-Ticket (EasyCard/iPass)": "電子票證 (悠遊卡/一卡通)", + "Easy Wallet": "悠遊付", "Electronic Invoice": "電子發票", "Electronic Invoices": "電子發票", "Elevator descending": "升降平台下降中", @@ -712,6 +716,7 @@ "Issued At": "開立時間", "Item List": "商品清單", "Items": "筆", + "JKO Pay": "街口支付", "JKO_MERCHANT_ID": "街口支付 商店代號", "Japanese": "日文", "Inactive": "已停用", @@ -722,7 +727,8 @@ "LEVEL TYPE": "層級類型", "LINE Pay Direct": "LINE Pay 官方直連", "LINE Pay Direct Settings Description": "LINE Pay 官方直連設定", - "LINE_MERCHANT_ID": "LINE Pay 商店代號", + "LINE Pay": "LINE Pay", + "LINE_PAY_CHANNEL_ID": "LINE Pay 頻道 ID", "LIVE": "實時", "Last Communication": "最後通訊", "Last Heartbeat": "最後心跳時間", @@ -882,7 +888,22 @@ "Member List": "會員列表", "Member Management": "會員管理", "Member Price": "會員價", + "Member + 1": "會員 + 1", + "Member + 2": "會員 + 2", + "Member + 3": "會員 + 3", + "Member + 4": "會員 + 4", + "Member + 5": "會員 + 5", + "Member + 6": "會員 + 6", + "Member + 7": "會員 + 7", + "Member + 8": "會員 + 8", + "Member + 9": "會員 + 9", + "Member + LINE Pay": "會員 + LINE Pay", + "Member + JKO Pay": "會員 + 街口支付", + "Member + Easy Wallet": "會員 + 悠遊付", + "Member + Pi Pay": "會員 + Pi 拍錢包", + "Member + PlusPay": "會員 + 全盈+PAY", "Member Status": "會員狀態", + "Member Verify Pickup": "會員驗證取貨", "Member System": "會員系統", "Membership Tiers": "會員等級", "Menu Permissions": "選單權限", @@ -1151,10 +1172,22 @@ "Please select a material": "請選擇素材", "Please select a slot": "請選擇貨道", "Please select warehouse and machine": "請選擇倉庫和機台", + "Pi Pay": "Pi 拍錢包", + "PlusPay": "全盈+PAY", "Point Rules": "點數規則", "Point Settings": "點數設定", "Points": "點數功能", - "Points Rule": "點數規則", + "Offline + 1": "離線 + 1", + "Offline + 2": "離線 + 2", + "Offline + 3": "離線 + 3", + "Offline + 4": "離線 + 4", + "Offline + 9": "離線 + 9", + "Offline + LINE Pay": "離線 + LINE Pay", + "Offline + JKO Pay": "離線 + 街口支付", + "Offline + Easy Wallet": "離線 + 悠遊付", + "Offline + Pi Pay": "離線 + Pi 拍錢包", + "Offline + PlusPay": "離線 + 全盈+PAY", + "Points/Voucher": "點數/優惠券", "Points Settings": "點數設定", "Points toggle": "點數開關", "Position": "投放位置", @@ -1206,6 +1239,7 @@ "Qty Change": "異動數量", "Quality": "品質 (Quality)", "Quantity": "數量", + "QR Code Payment": "掃碼支付", "Questionnaire": "問卷", "Quick Expiry Check": "效期快速檢查", "Quick Maintenance": "快速維護", @@ -1444,6 +1478,7 @@ "Spring Channel Limit": "彈簧貨道上限", "Spring Limit": "彈簧貨道上限", "Staff": "員工", + "Staff Card": "員工卡", "Staff Identification Management": "員工識別管理", "Staff List": "員工列表", "Staff Name": "員工姓名", diff --git a/resources/views/admin/sales/partials/tab-dispense.blade.php b/resources/views/admin/sales/partials/tab-dispense.blade.php index bd24a15..1354b75 100644 --- a/resources/views/admin/sales/partials/tab-dispense.blade.php +++ b/resources/views/admin/sales/partials/tab-dispense.blade.php @@ -1,39 +1,35 @@ {{-- Search Bar --}}
- + class="flex flex-col lg:flex-row lg:items-center flex-wrap gap-3 mb-8" @submit.prevent="fetchTabData('dispense')"> +
+ viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"> + class="py-2.5 pl-12 pr-6 block w-full luxury-input" placeholder="{{ __('Search Product / Slot...') }}">
- @foreach($machines as $m) - + @endforeach
{{-- 日期範圍 --}} -
- - + + + + - + placeholder="{{ __('Select Date Range') }}" + class="luxury-input py-2.5 pl-12 pr-6 block w-full text-sm font-bold cursor-pointer">
- - @else -
- {{ __('No related detail found') }} -
- @endif + {{-- Info Grid --}} +
+
+

{{ + __('Product / Slot') }}

+
+

+ {{ $log->product->name ?? 'Unknown' }} +

+

+ {{ __('Slot') }}: {{ $log->slot_no }} +

+
+
+
+

{{ + __('Amount') }}

+

{{ $log->amount }}

+
+
+

{{ + __('Dispense Time') }}

+

{{ $log->machine_time }}

+
+
+

{{ + __('Associated Order') }}

+

+ {{ $log->order->order_no ?? '---' }} +

- @empty -
- + + {{-- Action Buttons --}} +
+ @if($log->order_id) + + @else +
+ {{ __('No related detail found') }} +
+ @endif
+
+ @empty +
+ +
@endforelse
{{-- Pagination --}}
{{ $dispenseLogs->links('vendor.pagination.luxury', ['page_param' => 'dispense_page']) }} -
+ \ No newline at end of file diff --git a/resources/views/admin/sales/partials/tab-invoices.blade.php b/resources/views/admin/sales/partials/tab-invoices.blade.php index 9a41412..c3d9351 100644 --- a/resources/views/admin/sales/partials/tab-invoices.blade.php +++ b/resources/views/admin/sales/partials/tab-invoices.blade.php @@ -1,15 +1,13 @@ {{-- Search Bar --}} - + class="flex flex-col lg:flex-row lg:items-center flex-wrap gap-3 mb-8" @submit.prevent="fetchTabData('invoices')"> +
+ viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"> @@ -20,20 +18,19 @@
- @foreach($machines as $m) - + @endforeach
{{-- 日期範圍 --}} -
- - + + + + - + placeholder="{{ __('Select Date Range') }}" + class="luxury-input py-2.5 pl-12 pr-6 block w-full text-sm font-bold cursor-pointer">
- +
+
+

+ {{ $invoice->invoice_no }} +

+
+ + {{ $invoice->invoice_date }} + +

+ {{ ($invoice->machine_time ?? $invoice->created_at)->format('Y-m-d H:i:s') }} +

+
+
+ + + + + {{-- Info Grid --}} +
+
+

{{ + __('Machine') }}

+

+ {{ $invoice->machine->name ?? ($invoice->order->machine->name ?? 'Unknown') }} +

+

+ {{ $invoice->machine->serial_no ?? ($invoice->order->machine->serial_no ?? '---') }} +

+
+
+

{{ + __('Amount') }}

+

${{ number_format($invoice->amount, 0) + }}

+
+
+

{{ + __('Associated Order') }}

+

+ {{ $invoice->order->order_no ?? '---' }} +

+
+
+

{{ + __('Machine Time') }}

+

+ {{ ($invoice->machine_time ?? $invoice->created_at)->format('Y-m-d H:i:s') }} +

- @empty -
- + + {{-- Action Buttons --}} +
+
+
+ @empty +
+ +
@endforelse {{-- Pagination --}}
{{ $invoices->links('vendor.pagination.luxury', ['page_param' => 'invoices_page']) }} -
+ \ No newline at end of file diff --git a/resources/views/admin/sales/partials/tab-orders.blade.php b/resources/views/admin/sales/partials/tab-orders.blade.php index 590edf8..89b4b9e 100644 --- a/resources/views/admin/sales/partials/tab-orders.blade.php +++ b/resources/views/admin/sales/partials/tab-orders.blade.php @@ -279,7 +279,7 @@ {{-- Info Grid --}} -
+

{{ __('Order Items') }}

@@ -308,7 +308,7 @@

{{ __('Order Time') }}

- {{ $order->created_at->format('m-d H:i') }} + {{ $order->created_at->format('Y-m-d H:i:s') }} {{ $order->created_at->diffForHumans() }}

diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php index e36bffc..8fe7c73 100644 --- a/resources/views/layouts/admin.blade.php +++ b/resources/views/layouts/admin.blade.php @@ -110,35 +110,42 @@ window.location.reload(); } }"> -
+
-
@@ -160,7 +167,10 @@ class="flex items-center justify-between w-full py-2 px-3 rounded-xl text-sm text-gray-800 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300 transition-colors" :class="interval === opt ? 'bg-gray-50 dark:bg-gray-900/50 text-cyan-600 dark:text-cyan-400' : ''"> - + @@ -348,8 +358,7 @@ :class="[ sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0', sidebarCollapsed ? 'w-[60px]' : 'w-56' - ]" - x-init="$nextTick(() => { + ]" x-init="$nextTick(() => { const activeItem = $el.querySelector('.active, .bg-slate-100, .dark\\:bg-white\\/5'); if (activeItem) { activeItem.scrollIntoView({ block: 'center', behavior: 'instant' }); diff --git a/routes/api.php b/routes/api.php index b328b6f..01ba150 100644 --- a/routes/api.php +++ b/routes/api.php @@ -60,7 +60,6 @@ Route::prefix('v1')->middleware(['throttle:api'])->group(function () { // 機台狀態與相關同步 (B017, B710, B220) Route::get('machine/reload_msg/B017', [App\Http\Controllers\Api\V1\App\MachineController::class, 'getSlots']); - Route::post('machine/timer/B710', [App\Http\Controllers\Api\V1\App\MachineController::class, 'syncTimer']); Route::post('machine/coins/B220', [App\Http\Controllers\Api\V1\App\MachineController::class, 'syncCoinInventory']); Route::post('machine/member/verify/B650', [App\Http\Controllers\Api\V1\App\MachineController::class, 'verifyMember']);