[PROMOTE] 晉升 dev 變更至 demo 環境

1. [FEAT] 金流配置與機台系統設定整合進 B014,補完機台端設定下發(DevSet/CashSet/FunctionSet/ShoppingMode/OperationSet/HardwareSet、Line官方支付、卡片支付細項簡化、編輯機台區塊調整、API 文件同步)。
2. [FIX] 訪客取貨/通行頁 QR Code 改用公開路由,修正手機開啟失效。
3. [DOCS] 新增 CLAUDE.md 共用專案開發規範。
4. [CHORE] 將 Claude Code 個人設定排除於版控外。
5. [REFACTOR] 機台系統設定 settings JSON 化與編輯介面多語系/UI 優化。
This commit is contained in:
sky121113 2026-06-10 13:04:30 +08:00
commit 1a004a4d08
17 changed files with 1246 additions and 339 deletions

View File

@ -168,20 +168,38 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與
| :--- | :--- | :--- | :--- | :--- |
| machine | String | 是 | 機台編號 (serial_no) | M-001 |
- **資料來源**: 所有金流密鑰與電子發票設定,均取自機台關聯的「金流配置 (`payment_configs.settings`)」巢狀結構;機台須先在後台關聯一組金流配置 (`machines.payment_config_id`),未設值欄位回傳空字串 `""`
- **Response Body (Success 200 - Object):**
| 欄位 (Key) | 說明 | 備註 |
| 欄位 (Key) | 說明 | 來源 (payment_configs.settings) |
| :--- | :--- | :--- |
| **t050v01** | 機台序號 | 即 machine_id |
| **api_token** | **機台正式 Token** | 初始化後應存於本地,後續 API 認證用 |
| **t050v41** | 玉山特店編號 | ESUN Merchant ID |
| **t050v42** | 玉山終端編號 | ESUN Terminal ID |
| **t050v43** | 玉山 Hash Key | ESUN Hash |
| **t050v34** | 發票特店 ID | Invoice Merchant ID |
| **t050v35** | 發票 Hash Key | Invoice Key |
| **t050v36** | 發票 Hash IV | Invoice IV |
| **TP_APP_ID** | 趨勢支付 AppID | TrendPay ID |
| **TP_APP_KEY** | 趨勢支付 Key | TrendPay Key |
| **t050v01** | 機台序號 | machines.serial_no |
| **api_token** | **機台正式 Token** | machines.api_token初始化後存本地後續認證用|
| **t050v41** | 玉山特店編號 | `esun_scan.store_id` |
| **t050v42** | 玉山終端編號 | `esun_scan.term_id` |
| **t050v43** | 玉山 Hash Key | `esun_scan.key` |
| **t050v34** | 發票特店 ID | `ecpay_invoice.store_id` |
| **t050v35** | 發票 Hash Key | `ecpay_invoice.hash_key` |
| **t050v36** | 發票 Hash IV | `ecpay_invoice.hash_iv` |
| **t050v38** | 發票通知 Email | `ecpay_invoice.email` |
| **TP_APP_ID** | 趨勢/TapPay AppID | `tappay.app_id` |
| **TP_APP_KEY** | 趨勢/TapPay Key | `tappay.app_key` |
| **TP_PARTNER_KEY** | TapPay Partner Key | `tappay.partner_key` |
| **TP_LINE_MERCHANT_ID** | LINE Pay 特店 ID | `tappay.line_merchant_id` |
| **TP_JKO_MERCHANT_ID** | 街口支付 特店 ID | `tappay.jko_merchant_id` |
| **TP_PI_MERCHANT_ID** | Pi 拍錢包 特店 ID | `tappay.pi_merchant_id` |
| **TP_PS_MERCHANT_ID** | 全盈+Pay 特店 ID | `tappay.ps_merchant_id` |
| **TP_EASY_MERCHANT_ID** | 悠遊付 特店 ID | `tappay.easy_merchant_id` |
| **DevSet** | 支付旗標物件(命名沿用機台 `DevSetStructure`| 機台既有:`ShoppingCar`(shopping_cart_enabled)/`Invoice`(tax_invoice_enabled)/`DevNFCPay`(card_terminal_enabled)/`DevEsunPay`(scan_pay_esun_enabled)/`DevTapPay`(scan_pay_tappay_enabled)/`DevCash`(cash_module_enabled)/`DevLinePay`(scan_pay_linepay_enabled LINE Pay 官方直連)/`TapPay30`(tappay_linepay TapPay 底下 LINE Pay)/`TapPay31`(tappay_jkopay 街口)/`TapPay32`(tappay_easywallet 悠遊付)/`TapPay33`(tappay_pipay)/`TapPay34`(tappay_pluspay 全盈+)。**新定義**(機台待新增欄位)`DevCreditCard`(credit_card_enabled)/`DevMobilePay`(mobile_pay_enabled)/`DevCardPay`(card_pay_enabled)/`DevScanPay`(scan_pay_enabled)。`VMC`/`Electic` 雲端不下發。註LINE Pay 有兩條路線 —— `DevLinePay`=官方直連、`TapPay30`=經 TapPay兩者來源不同|
| **CashSet** | 現金面額旗標物件(對齊 `CashSetStructure`| machines.settings → `BillF1000`/`BillE500`/`BillD100`/`CoinF50`/`CoinE10`/`CoinD5`/`CoinC1` |
| **FunctionSet** | 非支付功能模組旗標物件(**新定義**,機台待實作)| machines.settings → `PickupModule`(pickup_module_enabled)/`PickupCode`(pickup_code_enabled)/`PassCode`(pass_code_enabled)/`WelcomeGift`(welcome_gift_enabled)/`MemberSystem`(member_system_enabled)/`AmbientTemp`(ambient_temp_monitoring_enabled) |
| **ShoppingMode** | 購物方式(字串,**新定義**| machines.settings.shopping_mode`basic` / `employee_card` / `pickup_sheet` |
| **OperationSet** | 運作參數(**新定義**,來源 machines 實體欄位)| `CardReaderSeconds`(card_reader_seconds 整數)/`PaymentBufferSeconds`(payment_buffer_seconds 整數)/`CheckoutTime1`(card_reader_checkout_time_1 時間字串)/`CheckoutTime2`(card_reader_checkout_time_2)/`HeatingStartTime`(heating_start_time)/`HeatingEndTime`(heating_end_time) |
| **HardwareSet** | 硬體與貨道(**新定義**,來源 machines 實體欄位)| `CardReaderNo`(card_reader_no 字串)/`SpringSlot1_10`~`SpringSlot51_60`(is_spring_slot_* 布林true=彈簧 / false=履帶) |
> 註:
> - 金流密鑰/發票來源已由「公司設定 (companies.settings)」改為「金流配置 (payment_configs.settings)」,並新增 `t050v38` 發票通知 Email。
> - 機台系統設定全部以機台端 `*Set` + PascalCase 風格下發(`DevSet`/`CashSet`/`FunctionSet`/`ShoppingMode`/`OperationSet`/`HardwareSet`),不再有原始 key 雜燴物件。`DevSet`/`CashSet` 對齊機台既有結構;其餘(含 `DevCreditCard/DevMobilePay/DevCardPay/DevScanPay`、`FunctionSet`、`ShoppingMode`、`OperationSet`、`HardwareSet`)為新定義,機台 App 端需另案新增對應結構與消費邏輯。旗標/設定來源為 `machines.settings`,運作參數與硬體貨道來源為 machines 實體欄位。
---

4
.gitignore vendored
View File

@ -22,3 +22,7 @@ yarn-error.log
/docs/pptx
/scratch
/.antigravitycli
# Claude Code 個人設定(權限授權等,不進版控)
/.claude/settings.json
/.claude/settings.local.json

16
CLAUDE.md Normal file
View File

@ -0,0 +1,16 @@
# star-cloud — 專案開發規範Claude Code
> 本專案的開發規範與 Antigravity 共用**同一份來源**`.agents/rules/`。
> 下方以 `@` import 載入,避免重複維護。**要修改規範請直接編輯 `.agents/rules/` 內的檔案**,不要改這裡。
## 一律遵循的專案規範always-on
@.agents/rules/framework.md
@.agents/rules/api-rules.md
@.agents/rules/rbac-rules.md
@.agents/rules/skill-trigger.md
## Claude 專屬補充
- `.agents/rules/``skill-trigger.md` 原為 Antigravity 撰寫,其中提到的 `view_file` 工具,在 Claude 對應為 `Read``.agents/skills/` 的 SKILL.md 可用 `Read` 讀取後依其指引作業。
- 提交訊息規範(繁體中文、`[FEAT]/[FIX]/[DOCS]/[STYLE]/[REFACTOR]` 前綴 + 數字列表與環境晉升dev → demo → main流程已封裝為使用者層自訂指令 `/now-push`、`/start-task`、`/promote-env`、`/hotfix-prod`,需要時可直接呼叫。

View File

@ -212,15 +212,12 @@ class MachineSettingController extends AdminController
'heating_end_time' => 'nullable|string',
'card_reader_no' => 'nullable|string|max:255',
'key_no' => 'nullable|string|max:255',
'invoice_status' => 'required|integer|in:0,1,2',
'welcome_gift_enabled' => 'boolean',
'is_spring_slot_1_10' => 'boolean',
'is_spring_slot_11_20' => 'boolean',
'is_spring_slot_21_30' => 'boolean',
'is_spring_slot_31_40' => 'boolean',
'is_spring_slot_41_50' => 'boolean',
'is_spring_slot_51_60' => 'boolean',
'member_system_enabled' => 'boolean',
'tax_invoice_enabled' => 'boolean',
'card_terminal_enabled' => 'boolean',
'scan_pay_esun_enabled' => 'boolean',
@ -347,13 +344,87 @@ class MachineSettingController extends AdminController
'shopping_cart_enabled',
'welcome_gift_enabled',
'cash_module_enabled',
'pickup_module_enabled',
'member_system_enabled',
'ambient_temp_monitoring_enabled',
];
$shoppingMode = $settings['shopping_mode'] ?? 'basic';
$data = [];
foreach ($allowedFields as $field) {
$data[$field] = isset($settings[$field]) ? (bool)$settings[$field] : false;
}
$jsonSettings = $machine->settings ?? [];
$jsonSettings['shopping_mode'] = $shoppingMode;
if ($shoppingMode !== 'basic') {
$data['card_terminal_enabled'] = false;
$data['scan_pay_esun_enabled'] = false;
$data['scan_pay_linepay_enabled'] = false;
$data['shopping_cart_enabled'] = false;
$data['welcome_gift_enabled'] = false;
$data['cash_module_enabled'] = false;
$data['pickup_module_enabled'] = false;
$jsonSettings['credit_card_enabled'] = false;
$jsonSettings['mobile_pay_enabled'] = false;
$jsonSettings['card_pay_enabled'] = false;
$jsonSettings['scan_pay_enabled'] = false;
$jsonSettings['scan_pay_tappay_enabled'] = false;
$jsonSettings['tappay_linepay'] = false;
$jsonSettings['tappay_jkopay'] = false;
$jsonSettings['tappay_pipay'] = false;
$jsonSettings['tappay_pluspay'] = false;
$jsonSettings['tappay_easywallet'] = false;
$jsonSettings['cash_bill_1000'] = false;
$jsonSettings['cash_bill_500'] = false;
$jsonSettings['cash_bill_100'] = false;
$jsonSettings['cash_coin_50'] = false;
$jsonSettings['cash_coin_10'] = false;
$jsonSettings['cash_coin_5'] = false;
$jsonSettings['cash_coin_1'] = false;
$jsonSettings['pickup_code_enabled'] = false;
$jsonSettings['pass_code_enabled'] = false;
} else {
$jsonSettings['credit_card_enabled'] = isset($settings['credit_card_enabled']) ? (bool)$settings['credit_card_enabled'] : false;
$jsonSettings['mobile_pay_enabled'] = isset($settings['mobile_pay_enabled']) ? (bool)$settings['mobile_pay_enabled'] : false;
$jsonSettings['card_pay_enabled'] = isset($settings['card_pay_enabled']) ? (bool)$settings['card_pay_enabled'] : false;
$jsonSettings['scan_pay_enabled'] = isset($settings['scan_pay_enabled']) ? (bool)$settings['scan_pay_enabled'] : false;
$jsonSettings['scan_pay_tappay_enabled'] = isset($settings['scan_pay_tappay_enabled']) ? (bool)$settings['scan_pay_tappay_enabled'] : false;
$jsonSettings['tappay_linepay'] = isset($settings['tappay_linepay']) ? (bool)$settings['tappay_linepay'] : false;
$jsonSettings['tappay_jkopay'] = isset($settings['tappay_jkopay']) ? (bool)$settings['tappay_jkopay'] : false;
$jsonSettings['tappay_pipay'] = isset($settings['tappay_pipay']) ? (bool)$settings['tappay_pipay'] : false;
$jsonSettings['tappay_pluspay'] = isset($settings['tappay_pluspay']) ? (bool)$settings['tappay_pluspay'] : false;
$jsonSettings['tappay_easywallet'] = isset($settings['tappay_easywallet']) ? (bool)$settings['tappay_easywallet'] : false;
$jsonSettings['cash_bill_1000'] = isset($settings['cash_bill_1000']) ? (bool)$settings['cash_bill_1000'] : false;
$jsonSettings['cash_bill_500'] = isset($settings['cash_bill_500']) ? (bool)$settings['cash_bill_500'] : false;
$jsonSettings['cash_bill_100'] = isset($settings['cash_bill_100']) ? (bool)$settings['cash_bill_100'] : false;
$jsonSettings['cash_coin_50'] = isset($settings['cash_coin_50']) ? (bool)$settings['cash_coin_50'] : false;
$jsonSettings['cash_coin_10'] = isset($settings['cash_coin_10']) ? (bool)$settings['cash_coin_10'] : false;
$jsonSettings['cash_coin_5'] = isset($settings['cash_coin_5']) ? (bool)$settings['cash_coin_5'] : false;
$jsonSettings['cash_coin_1'] = isset($settings['cash_coin_1']) ? (bool)$settings['cash_coin_1'] : false;
$jsonSettings['pickup_code_enabled'] = isset($settings['pickup_code_enabled']) ? (bool)$settings['pickup_code_enabled'] : false;
$jsonSettings['pass_code_enabled'] = isset($settings['pass_code_enabled']) ? (bool)$settings['pass_code_enabled'] : false;
}
foreach ($allowedFields as $field) {
$jsonSettings[$field] = $data[$field];
}
$machine->update([
'settings' => $jsonSettings,
'updater_id' => auth()->id()
]);
// 同時更新 model 的屬性欄位 (以防 mutator 同步,以及確保 dirty check 正確)
$machine->update(array_merge($data, ['updater_id' => auth()->id()]));
if ($request->expectsJson()) {

View File

@ -423,37 +423,108 @@ class MachineController extends Controller
], 404);
}
// 2. 獲取關聯設定 (依據使用者要求,跳過權限校驗,只要有序號即可獲取)
// 2. 獲取金流配置 (依據使用者要求,跳過權限校驗,只要有序號即可獲取)
// 來源統一為 payment_configs.settings 的巢狀結構 (對齊「編輯金流配置」表單)
$paymentSettings = $machine->paymentConfig->settings ?? [];
$companySettings = $machine->company->settings ?? [];
// 4. 映射 App 預期欄位 (嚴格遵守 HttpAPI.java 結構)
// 4. 映射 App 預期欄位 (輸出鍵維持 HttpAPI.java 結構,僅改值來源為巢狀)
$data = [
't050v01' => $machine->serial_no,
'api_token' => $machine->api_token, // 向 App 核發正式通訊 Token
// 玉山支付
't050v41' => $paymentSettings['esun_store_id'] ?? '',
't050v42' => $paymentSettings['esun_term_id'] ?? '',
't050v43' => $paymentSettings['esun_hash'] ?? '',
// 玉山掃碼 (esun_scan)
't050v41' => data_get($paymentSettings, 'esun_scan.store_id') ?? '',
't050v42' => data_get($paymentSettings, 'esun_scan.term_id') ?? '',
't050v43' => data_get($paymentSettings, 'esun_scan.key') ?? '',
// 電子發票 (綠界)
't050v34' => $companySettings['invoice_merchant_id'] ?? '',
't050v35' => $companySettings['invoice_hash_key'] ?? '',
't050v36' => $companySettings['invoice_hash_iv'] ?? '',
't050v38' => $companySettings['invoice_email'] ?? '',
// 綠界電子發票 (ecpay_invoice) — 改讀金流配置,不再讀 company.settings
't050v34' => data_get($paymentSettings, 'ecpay_invoice.store_id') ?? '',
't050v35' => data_get($paymentSettings, 'ecpay_invoice.hash_key') ?? '',
't050v36' => data_get($paymentSettings, 'ecpay_invoice.hash_iv') ?? '',
't050v38' => data_get($paymentSettings, 'ecpay_invoice.email') ?? '',
// 趨勢支付 (TrendPay/Greenpay)
'TP_APP_ID' => $paymentSettings['tp_app_id'] ?? '',
'TP_APP_KEY' => $paymentSettings['tp_app_key'] ?? '',
'TP_PARTNER_KEY' => $paymentSettings['tp_partner_key'] ?? '',
// TapPay / 趨勢支付 (tappay)
'TP_APP_ID' => data_get($paymentSettings, 'tappay.app_id') ?? '',
'TP_APP_KEY' => data_get($paymentSettings, 'tappay.app_key') ?? '',
'TP_PARTNER_KEY' => data_get($paymentSettings, 'tappay.partner_key') ?? '',
// 各類行動支付特店 ID
'TP_LINE_MERCHANT_ID' => $paymentSettings['tp_line_merchant_id'] ?? '',
'TP_PS_MERCHANT_ID' => $paymentSettings['tp_ps_merchant_id'] ?? '',
'TP_EASY_MERCHANT_ID' => $paymentSettings['tp_easy_merchant_id'] ?? '',
'TP_PI_MERCHANT_ID' => $paymentSettings['tp_pi_merchant_id'] ?? '',
'TP_JKO_MERCHANT_ID' => $paymentSettings['tp_jko_merchant_id'] ?? '',
// 各類行動支付特店 ID (tappay.*_merchant_id)
'TP_LINE_MERCHANT_ID' => data_get($paymentSettings, 'tappay.line_merchant_id') ?? '',
'TP_PS_MERCHANT_ID' => data_get($paymentSettings, 'tappay.ps_merchant_id') ?? '',
'TP_EASY_MERCHANT_ID' => data_get($paymentSettings, 'tappay.easy_merchant_id') ?? '',
'TP_PI_MERCHANT_ID' => data_get($paymentSettings, 'tappay.pi_merchant_id') ?? '',
'TP_JKO_MERCHANT_ID' => data_get($paymentSettings, 'tappay.jko_merchant_id') ?? '',
];
// 5. 機台系統設定 (machines.settings) → 全部以機台端 *Set + PascalCase 風格下發。
// 註:機台 App 端目前讀本地設定,需另案修改 App 才會實際消費此處下發值。
$s = $machine->settings ?? [];
// 5-1 DevSet支付旗標命名沿用機台 DevSetStructureDevCreditCard/DevMobilePay/
// DevCardPay/DevScanPay 為我方新定義,機台端需比照新增欄位)
$data['DevSet'] = [
'ShoppingCar' => (bool) ($s['shopping_cart_enabled'] ?? false), // 購物車
'Invoice' => (bool) ($s['tax_invoice_enabled'] ?? false), // 電子發票
'DevNFCPay' => (bool) ($s['card_terminal_enabled'] ?? false), // 刷卡機(總開關)
'DevCreditCard' => (bool) ($s['credit_card_enabled'] ?? false), // 信用卡支付(新定義)
'DevMobilePay' => (bool) ($s['mobile_pay_enabled'] ?? false), // 手機支付(新定義)
'DevCardPay' => (bool) ($s['card_pay_enabled'] ?? false), // 卡片支付(新定義)
'DevScanPay' => (bool) ($s['scan_pay_enabled'] ?? false), // 掃碼(總開關,新定義)
'DevEsunPay' => (bool) ($s['scan_pay_esun_enabled'] ?? false), // 玉山掃碼
'DevTapPay' => (bool) ($s['scan_pay_tappay_enabled'] ?? false), // TapPay 掃碼
'DevCash' => (bool) ($s['cash_module_enabled'] ?? false), // 現金
'DevLinePay' => (bool) ($s['scan_pay_linepay_enabled'] ?? false), // LINE Pay 官方直連Line官方支付與 TapPay30 不同)
'TapPay30' => (bool) ($s['tappay_linepay'] ?? false), // TapPay 底下的 LINE Pay
'TapPay31' => (bool) ($s['tappay_jkopay'] ?? false), // TapPay-街口支付
'TapPay32' => (bool) ($s['tappay_easywallet'] ?? false), // TapPay-悠遊付
'TapPay33' => (bool) ($s['tappay_pipay'] ?? false), // TapPay-Pi 支付
'TapPay34' => (bool) ($s['tappay_pluspay'] ?? false), // TapPay-全盈+支付
// 註VMC/Electic 為機台硬體類型,雲端無來源,由機台本地保留
];
// 5-2 CashSet現金面額對齊機台 CashSetStructure
$data['CashSet'] = [
'BillF1000' => (bool) ($s['cash_bill_1000'] ?? false),
'BillE500' => (bool) ($s['cash_bill_500'] ?? false),
'BillD100' => (bool) ($s['cash_bill_100'] ?? false),
'CoinF50' => (bool) ($s['cash_coin_50'] ?? false),
'CoinE10' => (bool) ($s['cash_coin_10'] ?? false),
'CoinD5' => (bool) ($s['cash_coin_5'] ?? false),
'CoinC1' => (bool) ($s['cash_coin_1'] ?? false),
];
// 5-3 FunctionSet非支付功能模組旗標我方新定義機台端待實作對應結構
$data['FunctionSet'] = [
'PickupModule' => (bool) ($s['pickup_module_enabled'] ?? false), // 取貨模組
'PickupCode' => (bool) ($s['pickup_code_enabled'] ?? false), // 取貨碼
'PassCode' => (bool) ($s['pass_code_enabled'] ?? false), // 通行碼
'WelcomeGift' => (bool) ($s['welcome_gift_enabled'] ?? false), // 來店禮
'MemberSystem' => (bool) ($s['member_system_enabled'] ?? false), // 會員系統
'AmbientTemp' => (bool) ($s['ambient_temp_monitoring_enabled'] ?? false), // 環境溫度監控
];
// 5-4 ShoppingMode購物方式頂層字串
$data['ShoppingMode'] = (string) ($s['shopping_mode'] ?? 'basic'); // basic / employee_card / pickup_sheet
// 5-5 OperationSet運作參數machines 實體欄位)
$data['OperationSet'] = [
'CardReaderSeconds' => (int) ($machine->card_reader_seconds ?? 0), // 刷卡機秒數
'PaymentBufferSeconds' => (int) ($machine->payment_buffer_seconds ?? 0), // 金流緩衝秒數
'CheckoutTime1' => (string) ($machine->card_reader_checkout_time_1 ?? ''), // 結帳時間 1
'CheckoutTime2' => (string) ($machine->card_reader_checkout_time_2 ?? ''), // 結帳時間 2
'HeatingStartTime' => (string) ($machine->heating_start_time ?? ''), // 加熱開始時間
'HeatingEndTime' => (string) ($machine->heating_end_time ?? ''), // 加熱結束時間
];
// 5-6 HardwareSet硬體與貨道machines 實體欄位SpringSlot* true=彈簧 / false=履帶)
$data['HardwareSet'] = [
'CardReaderNo' => (string) ($machine->card_reader_no ?? ''), // 刷卡機編號
'SpringSlot1_10' => (bool) $machine->is_spring_slot_1_10,
'SpringSlot11_20' => (bool) $machine->is_spring_slot_11_20,
'SpringSlot21_30' => (bool) $machine->is_spring_slot_21_30,
'SpringSlot31_40' => (bool) $machine->is_spring_slot_31_40,
'SpringSlot41_50' => (bool) $machine->is_spring_slot_41_50,
'SpringSlot51_60' => (bool) $machine->is_spring_slot_51_60,
];
return response()->json([

View File

@ -426,6 +426,137 @@ class Machine extends Model
->count();
}
// === settings JSON 重構 Accessors & Mutators ===
public function getShoppingModeAttribute(): string
{
return $this->settings['shopping_mode'] ?? 'basic';
}
public function setShoppingModeAttribute($value)
{
$settings = $this->settings ?? [];
$settings['shopping_mode'] = (string) $value;
$this->settings = $settings;
}
public function getTaxInvoiceEnabledAttribute(): bool
{
return (bool) ($this->settings['tax_invoice_enabled'] ?? ($this->attributes['tax_invoice_enabled'] ?? false));
}
public function setTaxInvoiceEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['tax_invoice_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['tax_invoice_enabled'] = (bool) $value;
}
public function getCardTerminalEnabledAttribute(): bool
{
return (bool) ($this->settings['card_terminal_enabled'] ?? ($this->attributes['card_terminal_enabled'] ?? false));
}
public function setCardTerminalEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['card_terminal_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['card_terminal_enabled'] = (bool) $value;
}
public function getScanPayEsunEnabledAttribute(): bool
{
return (bool) ($this->settings['scan_pay_esun_enabled'] ?? ($this->attributes['scan_pay_esun_enabled'] ?? false));
}
public function setScanPayEsunEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['scan_pay_esun_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['scan_pay_esun_enabled'] = (bool) $value;
}
public function getScanPayLinepayEnabledAttribute(): bool
{
return (bool) ($this->settings['scan_pay_linepay_enabled'] ?? ($this->attributes['scan_pay_linepay_enabled'] ?? false));
}
public function setScanPayLinepayEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['scan_pay_linepay_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['scan_pay_linepay_enabled'] = (bool) $value;
}
public function getShoppingCartEnabledAttribute(): bool
{
return (bool) ($this->settings['shopping_cart_enabled'] ?? ($this->attributes['shopping_cart_enabled'] ?? false));
}
public function setShoppingCartEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['shopping_cart_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['shopping_cart_enabled'] = (bool) $value;
}
public function getWelcomeGiftEnabledAttribute(): bool
{
return (bool) ($this->settings['welcome_gift_enabled'] ?? ($this->attributes['welcome_gift_enabled'] ?? false));
}
public function setWelcomeGiftEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['welcome_gift_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['welcome_gift_enabled'] = (bool) $value;
}
public function getCashModuleEnabledAttribute(): bool
{
return (bool) ($this->settings['cash_module_enabled'] ?? ($this->attributes['cash_module_enabled'] ?? false));
}
public function setCashModuleEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['cash_module_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['cash_module_enabled'] = (bool) $value;
}
public function getMemberSystemEnabledAttribute(): bool
{
return (bool) ($this->settings['member_system_enabled'] ?? ($this->attributes['member_system_enabled'] ?? false));
}
public function setMemberSystemEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['member_system_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['member_system_enabled'] = (bool) $value;
}
public function getAmbientTempMonitoringEnabledAttribute(): bool
{
return (bool) ($this->settings['ambient_temp_monitoring_enabled'] ?? ($this->attributes['ambient_temp_monitoring_enabled'] ?? false));
}
public function setAmbientTempMonitoringEnabledAttribute($value)
{
$settings = $this->settings ?? [];
$settings['ambient_temp_monitoring_enabled'] = (bool) $value;
$this->settings = $settings;
$this->attributes['ambient_temp_monitoring_enabled'] = (bool) $value;
}
public function users()
{
return $this->belongsToMany(\App\Models\System\User::class);

View File

@ -78,7 +78,7 @@ return [
'slug' => 'b014-config-download',
'method' => 'GET',
'path' => '/api/v1/app/machine/setting/B014',
'description' => '透過此介面下載金流金鑰、電子發票設定與機台專屬通訊 Token。',
'description' => '透過此介面下載金流金鑰、電子發票設定與機台專屬通訊 Token。金流密鑰與發票設定均取自機台關聯的「金流配置 (payment_configs.settings)」,未設值欄位回傳空字串。',
'headers' => [
'Content-Type' => 'application/json',
],
@ -94,18 +94,102 @@ return [
'success' => [
'type' => 'boolean',
'description' => '是否成功',
'example' => true
],
'data' => [
'type' => 'object',
'description' => '配置物件。包含t050v01 (序號), api_token (通訊 Token), t050v41~43 (玉山設定), t050v34~38 (發票設定), TP_... (趨勢/手機支付設定)',
'example' => [
't050v01' => 'SN202604130001',
'api_token' => 'mac_token_...',
't050v41' => '80812345',
't050v34' => '2000132',
'TP_APP_ID' => 'GP_001'
]
'description' => '配置物件,下列各欄位皆位於 data 之下。金鑰/發票來源為機台關聯的「金流配置 (payment_configs.settings)」DevSet / CashSet / FunctionSet / ShoppingMode 來源為「機台系統設定 (machines.settings)」OperationSet / HardwareSet 來源為 machines 實體欄位,皆採機台端 *Set + PascalCase 風格。',
],
'data.t050v01' => [
'type' => 'string',
'description' => '機台序號 ← machines.serial_no',
],
'data.api_token' => [
'type' => 'string',
'description' => '機台正式通訊 Token ← machines.api_token初始化後存本地後續 API 認證用)',
],
'data.t050v41' => [
'type' => 'string',
'description' => '玉山掃碼 StoreID ← 金流配置 esun_scan.store_id',
],
'data.t050v42' => [
'type' => 'string',
'description' => '玉山掃碼 TermID ← 金流配置 esun_scan.term_id',
],
'data.t050v43' => [
'type' => 'string',
'description' => '玉山掃碼 Key ← 金流配置 esun_scan.key',
],
'data.t050v34' => [
'type' => 'string',
'description' => '綠界發票 商店代號 ← 金流配置 ecpay_invoice.store_id',
],
'data.t050v35' => [
'type' => 'string',
'description' => '綠界發票 HashKey ← 金流配置 ecpay_invoice.hash_key',
],
'data.t050v36' => [
'type' => 'string',
'description' => '綠界發票 HashIV ← 金流配置 ecpay_invoice.hash_iv',
],
'data.t050v38' => [
'type' => 'string',
'description' => '綠界發票 通知 Email ← 金流配置 ecpay_invoice.email',
],
'data.TP_APP_ID' => [
'type' => 'string',
'description' => 'TapPay App ID ← 金流配置 tappay.app_id',
],
'data.TP_APP_KEY' => [
'type' => 'string',
'description' => 'TapPay App Key ← 金流配置 tappay.app_key',
],
'data.TP_PARTNER_KEY' => [
'type' => 'string',
'description' => 'TapPay Partner Key ← 金流配置 tappay.partner_key',
],
'data.TP_LINE_MERCHANT_ID' => [
'type' => 'string',
'description' => 'LINE Pay 特店 ID ← 金流配置 tappay.line_merchant_id',
],
'data.TP_JKO_MERCHANT_ID' => [
'type' => 'string',
'description' => '街口支付 特店 ID ← 金流配置 tappay.jko_merchant_id',
],
'data.TP_PI_MERCHANT_ID' => [
'type' => 'string',
'description' => 'Pi 拍錢包 特店 ID ← 金流配置 tappay.pi_merchant_id',
],
'data.TP_PS_MERCHANT_ID' => [
'type' => 'string',
'description' => '全盈+Pay 特店 ID ← 金流配置 tappay.ps_merchant_id',
],
'data.TP_EASY_MERCHANT_ID' => [
'type' => 'string',
'description' => '悠遊付 特店 ID ← 金流配置 tappay.easy_merchant_id',
],
'data.DevSet' => [
'type' => 'object',
'description' => "支付旗標(命名沿用機台 DevSetStructure布林。機台既有欄位\n• ShoppingCar ← shopping_cart_enabled購物車\n• Invoice ← tax_invoice_enabled電子發票\n• DevNFCPay ← card_terminal_enabled刷卡機總開關\n• DevEsunPay ← scan_pay_esun_enabled玉山掃碼\n• DevTapPay ← scan_pay_tappay_enabledTapPay 掃碼)\n• DevCash ← cash_module_enabled現金\n• DevLinePay ← scan_pay_linepay_enabledLINE Pay 官方直連)\n• TapPay30 ← tappay_linepayTapPay 底下的 LINE Pay\n• TapPay31 ← tappay_jkopay街口支付\n• TapPay32 ← tappay_easywallet悠遊付\n• TapPay33 ← tappay_pipayPi 支付)\n• TapPay34 ← tappay_pluspay全盈+支付)\n新定義(機台端待新增欄位):\n• DevCreditCard ← credit_card_enabled信用卡\n• DevMobilePay ← mobile_pay_enabled手機支付\n• DevCardPay ← card_pay_enabled卡片支付\n• DevScanPay ← scan_pay_enabled掃碼總開關\nVMC/Electic 為機台硬體類型,雲端不下發)",
],
'data.CashSet' => [
'type' => 'object',
'description' => "現金面額旗標(命名對齊機台端 CashSetStructure布林\n• BillF1000 / BillE500 / BillD100 ← cash_bill_1000 / 500 / 100\n• CoinF50 / CoinE10 / CoinD5 / CoinC1 ← cash_coin_50 / 10 / 5 / 1",
],
'data.FunctionSet' => [
'type' => 'object',
'description' => "非支付功能模組旗標(新定義,機台端待實作對應結構;布林):\n• PickupModule ← pickup_module_enabled取貨模組\n• PickupCode ← pickup_code_enabled取貨碼\n• PassCode ← pass_code_enabled通行碼\n• WelcomeGift ← welcome_gift_enabled來店禮\n• MemberSystem ← member_system_enabled會員系統\n• AmbientTemp ← ambient_temp_monitoring_enabled環境溫度監控",
],
'data.ShoppingMode' => [
'type' => 'string',
'description' => '購物方式(新定義)← machines.settings.shopping_modebasic / employee_card / pickup_sheet',
],
'data.OperationSet' => [
'type' => 'object',
'description' => "運作參數(新定義;來源 machines 實體欄位):\n• CardReaderSeconds ← card_reader_seconds整數刷卡機秒數\n• PaymentBufferSeconds ← payment_buffer_seconds整數金流緩衝秒數\n• CheckoutTime1 ← card_reader_checkout_time_1時間字串\n• CheckoutTime2 ← card_reader_checkout_time_2\n• HeatingStartTime ← heating_start_time加熱開始\n• HeatingEndTime ← heating_end_time加熱結束",
],
'data.HardwareSet' => [
'type' => 'object',
'description' => "硬體與貨道(新定義;來源 machines 實體欄位):\n• CardReaderNo ← card_reader_no字串刷卡機編號\n• SpringSlot1_10 / 11_20 / 21_30 / 31_40 / 41_50 / 51_60 ← is_spring_slot_*布林true=彈簧 / false=履帶)",
],
],
'request' => [],
@ -119,10 +203,73 @@ return [
't050v42' => '9001',
't050v43' => 'hash_key',
't050v34' => '2000132',
'TP_APP_ID' => 'GP_001'
't050v35' => 'invoice_hash_key',
't050v36' => 'invoice_hash_iv',
't050v38' => 'invoice@example.com',
'TP_APP_ID' => 'GP_001',
'TP_APP_KEY' => 'app_key_...',
'TP_PARTNER_KEY' => 'partner_key_...',
'TP_LINE_MERCHANT_ID' => 'LINE_M_001',
'TP_JKO_MERCHANT_ID' => 'JKO_M_001',
'TP_PI_MERCHANT_ID' => 'PI_M_001',
'TP_PS_MERCHANT_ID' => 'PS_M_001',
'TP_EASY_MERCHANT_ID' => 'EASY_M_001',
'DevSet' => [
'ShoppingCar' => true,
'Invoice' => true,
'DevNFCPay' => true,
'DevCreditCard' => true,
'DevMobilePay' => true,
'DevCardPay' => false,
'DevScanPay' => true,
'DevEsunPay' => true,
'DevTapPay' => false,
'DevCash' => true,
'DevLinePay' => true,
'TapPay30' => false,
'TapPay31' => true,
'TapPay32' => false,
'TapPay33' => false,
'TapPay34' => false,
],
'CashSet' => [
'BillF1000' => true,
'BillE500' => true,
'BillD100' => true,
'CoinF50' => true,
'CoinE10' => true,
'CoinD5' => true,
'CoinC1' => true,
],
'FunctionSet' => [
'PickupModule' => false,
'PickupCode' => false,
'PassCode' => false,
'WelcomeGift' => false,
'MemberSystem' => false,
'AmbientTemp' => false,
],
'ShoppingMode' => 'basic',
'OperationSet' => [
'CardReaderSeconds' => 30,
'PaymentBufferSeconds' => 5,
'CheckoutTime1' => '22:30:00',
'CheckoutTime2' => '23:45:00',
'HeatingStartTime' => '00:00:00',
'HeatingEndTime' => '00:00:00',
],
'HardwareSet' => [
'CardReaderNo' => 'CR-001',
'SpringSlot1_10' => true,
'SpringSlot11_20' => false,
'SpringSlot21_30' => false,
'SpringSlot31_40' => false,
'SpringSlot41_50' => false,
'SpringSlot51_60' => false,
],
]
],
'notes' => '此 API 為機台初始化引導用,目前不強制驗證 User Token。'
'notes' => '此 API 為機台初始化引導用,目前不強制驗證 User Token。金流密鑰與發票設定來源為機台關聯的金流配置 (payment_configs)DevSet / CashSet / FunctionSet / ShoppingMode 來源為 machines.settings、OperationSet / HardwareSet 來源為 machines 實體欄位,全部採機台端 *Set + PascalCase 風格DevSet/CashSet 對齊機台既有結構,其餘為新定義,機台 App 端需另案實作)。'
],
[
'name' => 'B005: 廣告清單同步 (Ad Sync)',

View File

@ -221,6 +221,8 @@
"Barcode / Material": "Barcode / Material",
"Based on Hours": "Based on Hours",
"Basic Information": "Basic Information",
"Basic Mode": "Basic Mode",
"Basic Mode Features": "Basic Mode Features",
"Basic Settings": "Basic Settings",
"Basic Specifications": "Basic Specifications",
"Batch": "Batch",
@ -233,7 +235,12 @@
"Bento heating": "Bento heating",
"Bento machine cooling water tank empty": "Bento machine cooling water tank low water",
"Bento not detected": "Bento not detected",
"Bill": "Bill",
"Bill 100": "Bill 100",
"Bill 1000": "Bill 1000",
"Bill 500": "Bill 500",
"Bill Acceptor": "Bill Acceptor",
"Bill Denominations": "Bill Denominations",
"Bracelet drop not detected": "Bracelet drop not detected",
"Bracelet scan failed": "Bracelet scan failed",
"Branch": "Branch",
@ -263,6 +270,7 @@
"Cannot delete role with active users.": "Cannot delete role with active users.",
"Cannot delete warehouse with existing stock": "Cannot delete warehouse with existing stock",
"Card Machine System": "Card Machine System",
"Card Payment": "Card Payment",
"Card Reader": "Card Reader",
"Card Reader No": "Card Reader No",
"Card Reader Reboot": "Card Reader Reboot",
@ -276,6 +284,7 @@
"Cash Module": "Cash Module",
"Cash Module Feature": "Cash Module Feature",
"Cash Module Function": "Cash Module Function",
"Cash Payment": "Cash Payment",
"Category": "Category",
"Category Management": "Category Management",
"Category Name": "Category Name",
@ -312,7 +321,13 @@
"Close Panel": "Close Panel",
"Code": "Code",
"Code Copied": "Code Copied",
"Coin": "Coin",
"Coin 1": "Coin 1",
"Coin 10": "Coin 10",
"Coin 5": "Coin 5",
"Coin 50": "Coin 50",
"Coin Acceptor": "Coin Acceptor",
"Coin Denominations": "Coin Denominations",
"Coin/Banknote Machine": "Coin/Banknote Machine",
"Coin/Bill Acceptor": "Coin/Bill Acceptor",
"Command Center": "Command Center",
@ -418,6 +433,7 @@
"Creator": "Creator",
"Credit Card": "Credit Card",
"Credit Card / Contactless": "Credit Card / Contactless",
"Credit Card Payment": "Credit Card Payment",
"Critical": "Critical",
"Critical failures requiring immediate hands-on attention.": "Critical failures requiring immediate hands-on attention.",
"Cross-Company / Headquarter Global Stats": "Cross-Company / Headquarter Global Stats",
@ -585,12 +601,14 @@
"E.SUN QR Pay": "E.SUN QR Pay",
"E.SUN QR Scan": "E.SUN QR Scan",
"E.SUN QR Scan Settings Description": "E.SUN QR Scan Settings Description",
"EASY_MERCHANT_ID": "EASY_MERCHANT_ID",
"EASY_MERCHANT_ID": "EASY_MERCHANT_ID (EasyWallet)",
"ECPay Invoice": "ECPay Invoice",
"ECPay Invoice Settings Description": "ECPay Invoice Settings Description",
"ESUN": "ESUN",
"ESUN Scan Pay": "ESUN Scan Pay",
"Easy Wallet": "Easy Wallet",
"EasyCard": "EasyCard",
"EasyWallet": "EasyWallet",
"Edit": "Edit",
"Edit Account": "Edit Account",
"Edit Advertisement": "Edit Advertisement",
@ -604,6 +622,7 @@
"Edit Machine Model": "Edit Machine Model",
"Edit Machine Name": "Edit Machine Name",
"Edit Machine Settings": "Edit Machine Settings",
"Edit Machine System Settings": "Edit Machine System Settings",
"Edit Name": "Edit Name",
"Edit Pass Code": "Edit Pass Code",
"Edit Payment Config": "Edit Payment Config",
@ -915,16 +934,21 @@
"Inventory Stable": "Inventory Stable",
"Inventory synced with machine": "Inventory synced with machine",
"Invoice Date": "Invoice Date",
"Invoice HashIV": "Invoice HashIV",
"Invoice HashKey": "Invoice HashKey",
"Invoice Information": "Invoice Information",
"Invoice Notification Email": "Invoice Notification Email",
"Invoice Number": "Invoice Number",
"Invoice Number / Flow ID": "Invoice Number / Flow ID",
"Invoice Number / Time": "Invoice Number / Time",
"Invoice Status": "Invoice Status",
"Invoice Store ID": "Invoice Store ID",
"Issued At": "Issued At",
"Item List": "Item List",
"Items": "Items",
"JKO Pay": "JKO Pay",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID",
"JKOPAY": "JKOPAY",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID (JKOPAY)",
"Japanese": "Japanese",
"Joined": "Joined",
"Just now": "Just now",
@ -934,6 +958,9 @@
"LINE Pay": "LINE Pay",
"LINE Pay Direct": "LINE Pay Direct",
"LINE Pay Direct Settings Description": "LINE Pay Direct Settings Description",
"LINE-ChannelId": "LINE-ChannelId",
"LINE-ChannelSecret": "LINE-ChannelSecret",
"LINE_MERCHANT_ID": "LINE_MERCHANT_ID (LINE Pay)",
"LINE_PAY_CHANNEL_ID": "LINE_PAY_CHANNEL_ID",
"LIVE": "LIVE",
"Last 7 Days": "Last 7 Days",
@ -960,6 +987,7 @@
"Line Members": "Line Members",
"Line Official Account": "Line Official Account",
"Line Orders": "Line Orders",
"Line Pay": "Line Pay",
"Line Permissions": "Line Permissions",
"Line Products": "Line Products",
"LinePay": "LinePay",
@ -1174,6 +1202,7 @@
"Microwave push rod retract error (0223)": "Microwave push rod retract error (0223)",
"Milk dispense timeout": "Milk dispense timeout",
"Min 8 characters": "Min 8 characters",
"Mobile Payment": "Mobile Payment",
"Model": "Model",
"Model Default": "Model Default",
"Model Name": "Model Name",
@ -1389,12 +1418,12 @@
"Overall Capacity": "Overall Capacity",
"Owner": "Owner",
"PARTNER_KEY": "PARTNER_KEY",
"PI_MERCHANT_ID": "PI_MERCHANT_ID",
"PI_MERCHANT_ID": "PI_MERCHANT_ID (Pi Wallet)",
"PNG, JPG up to 2MB": "PNG, JPG up to 2MB",
"PNG, JPG, WEBP up to 10MB": "PNG, JPG, WEBP up to 10MB",
"POS Reboot": "POS Reboot",
"PS_LEVEL": "PS_LEVEL",
"PS_MERCHANT_ID": "PS_MERCHANT_ID",
"PS_MERCHANT_ID": "PS_MERCHANT_ID (PlusPay)",
"Page 0": "Page 0",
"Page 1": "Page 1",
"Page 2": "Page 2",
@ -1430,6 +1459,7 @@
"Pass code deleted.": "Pass code deleted.",
"Pass code disabled.": "Pass code disabled.",
"Pass code updated.": "Pass code updated.",
"Passcode": "Passcode",
"Password": "Password",
"Password updated successfully.": "Password updated successfully.",
"Payment & Invoice": "Payment & Invoice",
@ -1459,13 +1489,16 @@
"Phone": "Phone",
"Photo Slot": "Photo Slot",
"Pi Pay": "Pi Pay",
"Pi Wallet": "Pi Wallet",
"Picked up": "Picked up",
"Picked up Time": "Picked up Time",
"Pickup Code": "Pickup Code",
"Pickup Code (8 Digits)": "Pickup Code (8 Digits)",
"Pickup Codes": "Pickup Codes",
"Pickup Module": "Pickup Module",
"Pickup Recipient (Prescription Slip)": "Pickup Recipient (Prescription Slip)",
"Pickup Recipient Info": "Pickup Recipient Info",
"Pickup Sheet (Material No.)": "Pickup Sheet (Material No.)",
"Pickup Ticket": "Pickup Ticket",
"Pickup Voucher": "Pickup Voucher",
"Pickup code cancelled.": "Pickup code cancelled.",
@ -1717,8 +1750,12 @@
"Saved.": "Saved.",
"Saving...": "Saving...",
"Scale level and access control": "Scale level and access control",
"Scan Key": "Scan Key",
"Scan Pay": "Scan Pay",
"Scan Payment": "Scan Payment",
"Scan QR Code": "Scan QR Code",
"Scan Store ID": "Scan Store ID",
"Scan Term ID": "Scan Term ID",
"Scan this code at the machine or share the link with the customer.": "Scan this code at the machine or share the link with the customer.",
"Scan this code at the machine to authorize testing or maintenance.": "Scan this code at the machine to authorize testing or maintenance.",
"Scan this code to quickly access the maintenance form for this device.": "Scan this code to quickly access the maintenance form for this device.",
@ -1753,6 +1790,7 @@
"Search customers...": "Search customers...",
"Search logs...": "Search logs...",
"Search machine name or SN...": "Search machine name or SN...",
"Search machine name or code...": "Search machine name or code...",
"Search machine name, S/N, or location...": "Search machine name, S/N, or location...",
"Search machine name, serial no...": "Search machine name, serial no...",
"Search machines by name or serial...": "Search machines by name or serial...",
@ -1774,6 +1812,7 @@
"Security & State": "Security & State",
"Security Controls": "Security Controls",
"Select All": "Select All",
"Select All / Deselect All": "Select All / Deselect All",
"Select Cargo Lane": "Select Cargo Lane",
"Select Category": "Select Category",
"Select Company": "Select Company",
@ -1825,7 +1864,7 @@
"Setup Brand": "Setup Brand",
"Shopping Cart": "Shopping Cart",
"Shopping Cart Feature": "Shopping Cart Feature",
"Shopping Cart Function": "Shopping Cart Function",
"Shopping Mode": "Shopping Mode",
"Show": "Show",
"Show material code field in products": "Show material code field in products",
"Show points rules in products": "Show points rules in products",
@ -1984,6 +2023,7 @@
"System super admin accounts cannot be modified via this interface.": "System super admin accounts cannot be modified via this interface.",
"Systems Initializing": "Systems Initializing",
"Table View": "Table View",
"TapPay": "TapPay",
"TapPay Integration": "TapPay Integration",
"TapPay Integration Settings Description": "TapPay Integration Settings Description",
"Target": "Target",
@ -2252,7 +2292,6 @@
"Welcome Gift Code": "Welcome Gift Code",
"Welcome Gift Code (8 Digits)": "Welcome Gift Code (8 Digits)",
"Welcome Gift Feature": "Welcome Gift Feature",
"Welcome Gift Function": "Welcome Gift Function",
"Welcome Gift Name": "Welcome Gift Name",
"Welcome Gift Status": "Welcome Gift Status",
"Welcome Gifts": "Welcome Gifts",
@ -2342,6 +2381,8 @@
"fanon": "Fan turned on",
"files selected": "files selected",
"hours ago": "hours ago",
"iPASS": "iPASS",
"icash": "icash",
"image": "image",
"image_url": "image_url",
"info": "info",
@ -2472,5 +2513,6 @@
"video": "Video",
"visit_gift": "Visit Gift",
"vs Yesterday": "vs Yesterday",
"warning": "warning"
"warning": "warning",
"LINE Official Pay": "LINE Official Pay"
}

View File

@ -221,6 +221,8 @@
"Barcode / Material": "バーコード / 資材",
"Based on Hours": "時間ベースで計算",
"Basic Information": "基本情報",
"Basic Mode": "基本版",
"Basic Mode Features": "基本版ショッピング機能",
"Basic Settings": "基本設定",
"Basic Specifications": "基本仕様",
"Batch": "バッチ",
@ -233,7 +235,12 @@
"Bento heating": "弁当加熱中",
"Bento machine cooling water tank empty": "弁当機冷却水タンク空",
"Bento not detected": "弁当が検出されません",
"Bill": "紙幣",
"Bill 100": "100元紙幣受入",
"Bill 1000": "1000元紙幣受入",
"Bill 500": "500元紙幣受入",
"Bill Acceptor": "紙幣識別機",
"Bill Denominations": "紙幣受入金種",
"Bracelet drop not detected": "ブレスレット落下未検出",
"Bracelet scan failed": "ブレスレットスキャン失敗",
"Branch": "分庫",
@ -263,6 +270,7 @@
"Cannot delete role with active users.": "ユーザーが紐付けられているロールは削除できません。",
"Cannot delete warehouse with existing stock": "在庫がある倉庫は削除できません",
"Card Machine System": "カードリーダーシステム",
"Card Payment": "カード決済",
"Card Reader": "カードリーダー",
"Card Reader No": "カードリーダー番号",
"Card Reader Reboot": "カードリーダー再起動",
@ -273,9 +281,10 @@
"Card Terminal": "カード端末",
"Card Terminal System": "カードリーダーシステム",
"Card UID": "カードUID",
"Cash Module": "コイン・紙幣モジュール",
"Cash Module": "現金モジュール",
"Cash Module Feature": "現金モジュール機能",
"Cash Module Function": "現金モジュール機能",
"Cash Payment": "現金決済",
"Category": "カテゴリ",
"Category Management": "カテゴリ管理",
"Category Name": "カテゴリ名",
@ -312,7 +321,13 @@
"Close Panel": "パネルを閉じる",
"Code": "コード",
"Code Copied": "コードをコピーしました",
"Coin": "硬貨",
"Coin 1": "1元硬貨受入",
"Coin 10": "10元硬貨受入",
"Coin 5": "5元硬貨受入",
"Coin 50": "50元硬貨受入",
"Coin Acceptor": "硬貨機",
"Coin Denominations": "硬貨受入金種",
"Coin/Banknote Machine": "硬貨・紙幣機",
"Coin/Bill Acceptor": "硬貨・紙幣機",
"Command Center": "コマンドセンター",
@ -418,6 +433,7 @@
"Creator": "作成者",
"Credit Card": "クレジットカード",
"Credit Card / Contactless": "クレジットカード/非接触決済対応",
"Credit Card Payment": "クレジットカード決済",
"Critical": "深刻",
"Critical failures requiring immediate hands-on attention.": "即座に対処が必要な重大な障害。",
"Cross-Company / Headquarter Global Stats": "複数会社間 / 本部グローバル統計",
@ -581,16 +597,18 @@
"During OTA deployment, the device will install directly in the background without user confirmation.": "OTAデプロイ時、デバイスはユーザーの確認なしでバックグラウンドで直接インストールされます。",
"E-Ticket (EasyCard/iPass)": "電子チケット (EasyCard/iPass)",
"E.SUN Bank Scan": "玉山銀行スキャン",
"E.SUN Pay": "玉山 Pay",
"E.SUN Pay": "玉山ペイ",
"E.SUN QR Pay": "玉山銀行QR決済",
"E.SUN QR Scan": "玉山銀行ラベル決済",
"E.SUN QR Scan": "玉山スキャン",
"E.SUN QR Scan Settings Description": "玉山銀行スキャン決済設定",
"EASY_MERCHANT_ID": "Easy Wallet 加盟店ID",
"EASY_MERCHANT_ID": "EASY_MERCHANT_ID (悠遊付)",
"ECPay Invoice": "ECPay 電子領収書",
"ECPay Invoice Settings Description": "ECPay 電子領収書設定",
"ESUN": "玉山銀行",
"ESUN Scan Pay": "玉山スキャン決済",
"Easy Wallet": "悠遊付 (Easy Wallet)",
"EasyCard": "悠遊カード",
"EasyWallet": "悠遊付",
"Edit": "編集",
"Edit Account": "アカウント編集",
"Edit Advertisement": "広告編集",
@ -604,6 +622,7 @@
"Edit Machine Model": "機器モデル編集",
"Edit Machine Name": "機器名編集",
"Edit Machine Settings": "機器設定編集",
"Edit Machine System Settings": "機器システム設定編集",
"Edit Name": "名前編集",
"Edit Pass Code": "パスコード編集",
"Edit Payment Config": "決済設定編集",
@ -893,7 +912,7 @@
"Imported with errors. Please check the console.": "Imported with errors. Please check the console.",
"In Stock": "現在庫",
"Inactive": "停止中",
"Includes Credit Card/Mobile Pay": "クレジット/QR決済を含む",
"Includes Credit Card/Mobile Pay": "クレジット/モバイル決済",
"Indefinite": "無期限",
"Info": "情報",
"Inherit": "継承",
@ -915,16 +934,21 @@
"Inventory Stable": "在庫安定",
"Inventory synced with machine": "在庫を機器と同期しました",
"Invoice Date": "発行日",
"Invoice HashIV": "請求書HashIV",
"Invoice HashKey": "請求書HashKey",
"Invoice Information": "領収書情報",
"Invoice Notification Email": "請求書通知メール",
"Invoice Number": "領収書番号",
"Invoice Number / Flow ID": "領収書番号 / フローID",
"Invoice Number / Time": "領収書番号 / 時間",
"Invoice Status": "発行ステータス",
"Invoice Store ID": "請求書ストアID",
"Issued At": "発行日時",
"Item List": "商品リスト",
"Items": "件",
"JKO Pay": "街口支付 (JKO Pay)",
"JKO_MERCHANT_ID": "街口支付 (JKO Pay) 加盟店ID",
"JKOPAY": "JKOPAY",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID (街口支付)",
"Japanese": "日本語",
"Joined": "加入日",
"Just now": "たった今",
@ -934,6 +958,9 @@
"LINE Pay": "LINE Pay",
"LINE Pay Direct": "LINE Pay 直結",
"LINE Pay Direct Settings Description": "LINE Pay 直結設定",
"LINE-ChannelId": "LINE-ChannelId",
"LINE-ChannelSecret": "LINE-ChannelSecret",
"LINE_MERCHANT_ID": "LINE_MERCHANT_ID (LINE Pay)",
"LINE_PAY_CHANNEL_ID": "LINE Pay チャンネルID",
"LIVE": "ライブ",
"Last 7 Days": "過去7日間",
@ -960,6 +987,7 @@
"Line Members": "LINEメンバー",
"Line Official Account": "LINE公式アカウント",
"Line Orders": "LINE注文",
"Line Pay": "LINE Pay",
"Line Permissions": "LINE権限",
"Line Products": "LINE商品",
"LinePay": "LinePay",
@ -1174,6 +1202,7 @@
"Microwave push rod retract error (0223)": "電子レンジプッシュロッド引き込みエラー (0223)",
"Milk dispense timeout": "牛乳抽出タイムアウト",
"Min 8 characters": "最低 8文字",
"Mobile Payment": "モバイル決済",
"Model": "機器モデル",
"Model Default": "モデルデフォルト",
"Model Name": "モデル名",
@ -1389,12 +1418,12 @@
"Overall Capacity": "総在庫容量",
"Owner": "所有者",
"PARTNER_KEY": "PARTNER_KEY",
"PI_MERCHANT_ID": "Pi 拍錢包 加盟店ID",
"PI_MERCHANT_ID": "PI_MERCHANT_ID (Pi 拍錢包)",
"PNG, JPG up to 2MB": "PNG, JPG 最大 2MB",
"PNG, JPG, WEBP up to 10MB": "PNG, JPG, WEBP 最大 10MB",
"POS Reboot": "POS再起動",
"PS_LEVEL": "PS_LEVEL",
"PS_MERCHANT_ID": "全盈+Pay 加盟店ID",
"PS_MERCHANT_ID": "PS_MERCHANT_ID (全盈+Pay)",
"Page 0": "ページ 0 (オフライン)",
"Page 1": "ページ 1 (ホームページ)",
"Page 2": "ページ 2 (販売ページ)",
@ -1430,6 +1459,7 @@
"Pass code deleted.": "パスコードが削除されました。",
"Pass code disabled.": "パスコードが無効化されました。",
"Pass code updated.": "パスコードが更新されました。",
"Passcode": "通行コード",
"Password": "パスワード",
"Password updated successfully.": "パスワードが正常に更新されました。",
"Payment & Invoice": "決済・領収書",
@ -1459,13 +1489,16 @@
"Phone": "電話番号",
"Photo Slot": "写真スロット",
"Pi Pay": "Pi 拍錢包 (Pi Pay)",
"Pi Wallet": "Pi Wallet",
"Picked up": "受取済み",
"Picked up Time": "受取時間",
"Pickup Code": "受取コード",
"Pickup Code (8 Digits)": "受取コード (8桁)",
"Pickup Codes": "受取コード",
"Pickup Module": "受取モジュール",
"Pickup Recipient (Prescription Slip)": "受取者(処方箋)",
"Pickup Recipient Info": "受取者情報",
"Pickup Sheet (Material No.)": "ピッキングシート(材料番号)",
"Pickup Ticket": "商品受取チケット",
"Pickup Voucher": "受取票",
"Pickup code cancelled.": "受取コードがキャンセルされました。",
@ -1502,7 +1535,7 @@
"Please select an APK file to upload": "Please select an APK file to upload",
"Please select warehouse and machine": "倉庫と機器を選択してください",
"Please use our standard template to ensure data compatibility.": "データの互換性を確保するために、標準テンプレートを使用してください。",
"PlusPay": "全盈+PAY (PlusPay)",
"PlusPay": "PlusPay",
"Point Rules": "ポイントルール",
"Point Settings": "ポイント設定",
"Points": "ポイント",
@ -1717,8 +1750,12 @@
"Saved.": "保存しました。",
"Saving...": "保存中...",
"Scale level and access control": "スケールレベルとアクセス制御",
"Scan Key": "スキャンKey",
"Scan Pay": "スキャン決済",
"Scan Payment": "QRコード決済",
"Scan QR Code": "QRコードをスキャン",
"Scan Store ID": "スキャンStoreID",
"Scan Term ID": "スキャンTermID",
"Scan this code at the machine or share the link with the customer.": "機器でこのコードをスキャンするか、リンクを顧客と共有してください。",
"Scan this code at the machine to authorize testing or maintenance.": "機器でこのコードをスキャンして、テストまたはメンテナンスを承認します。",
"Scan this code to quickly access the maintenance form for this device.": "このQRコードをスキャンすると、このデバイスのメンテナンスフォームに素早くアクセスできます。",
@ -1753,6 +1790,7 @@
"Search customers...": "顧客を検索...",
"Search logs...": "ログを検索...",
"Search machine name or SN...": "機器名またはシリアル番号で検索...",
"Search machine name or code...": "機器名またはコードを検索...",
"Search machine name, S/N, or location...": "Search machine name, S/N, or location...",
"Search machine name, serial no...": "マシン名、シリアル番号で検索...",
"Search machines by name or serial...": "機器名またはシリアルで検索...",
@ -1774,6 +1812,7 @@
"Security & State": "セキュリティ・状態",
"Security Controls": "セキュリティ制御",
"Select All": "すべて選択",
"Select All / Deselect All": "すべて選択 / すべて解除",
"Select Cargo Lane": "スロットを選択",
"Select Category": "カテゴリを選択",
"Select Company": "会社を選択",
@ -1825,7 +1864,7 @@
"Setup Brand": "デザイン設定",
"Shopping Cart": "ショッピングカート",
"Shopping Cart Feature": "ショッピングカート機能",
"Shopping Cart Function": "ショッピングカート機能",
"Shopping Mode": "ショッピングモード",
"Show": "表示",
"Show material code field in products": "商品に資材コードフィールドを表示する",
"Show points rules in products": "商品にポイントルールフィールドを表示する",
@ -1876,7 +1915,7 @@
"Spring Channel Limit": "スプリングスロット上限",
"Spring Limit": "スプリング上限",
"Staff": "スタッフ",
"Staff Card": "スタッフカード",
"Staff Card": "社員カード",
"Staff Card Info": "スタッフカード情報",
"Staff Identification Management": "スタッフ識別管理",
"Staff List": "スタッフ一覧",
@ -1984,6 +2023,7 @@
"System super admin accounts cannot be modified via this interface.": "システム特権管理者アカウントはこのインターフェースから変更できません。",
"Systems Initializing": "システム初期化中",
"Table View": "リストビュー",
"TapPay": "TapPay",
"TapPay Integration": "TapPay 連携",
"TapPay Integration Settings Description": "TapPay 決済連携設定",
"Target": "対象",
@ -2252,7 +2292,6 @@
"Welcome Gift Code": "来店プレゼントコード",
"Welcome Gift Code (8 Digits)": "ウェルカムギフトコード (8桁)",
"Welcome Gift Feature": "ウェルカムギフト機能",
"Welcome Gift Function": "ウェルカムギフト機能",
"Welcome Gift Name": "ウェルカムギフト名",
"Welcome Gift Status": "来店ギフトステータス",
"Welcome Gifts": "ウェルカムギフト",
@ -2342,6 +2381,8 @@
"fanon": "ファン起動",
"files selected": "個のファイルを選択しました",
"hours ago": "時間前",
"iPASS": "iPASSカード",
"icash": "icashカード",
"image": "画像",
"image_url": "image_url",
"info": "一般",
@ -2472,5 +2513,6 @@
"video": "動画",
"visit_gift": "来店ギフト",
"vs Yesterday": "昨日比",
"warning": "警告"
"warning": "警告",
"LINE Official Pay": "LINE 公式決済"
}

View File

@ -221,6 +221,8 @@
"Barcode / Material": "條碼 / 物料編碼",
"Based on Hours": "依據時數計算",
"Basic Information": "基本資訊",
"Basic Mode": "基礎版",
"Basic Mode Features": "基礎版購物功能",
"Basic Settings": "基本設定",
"Basic Specifications": "基本規格",
"Batch": "批號",
@ -233,7 +235,12 @@
"Bento heating": "盒飯正在加熱",
"Bento machine cooling water tank empty": "盒飯機冷卻水箱缺水",
"Bento not detected": "沒檢測到盒飯",
"Bill": "鈔",
"Bill 100": "收鈔面額100",
"Bill 1000": "收鈔面額1000",
"Bill 500": "收鈔面額500",
"Bill Acceptor": "紙鈔機",
"Bill Denominations": "收鈔面額",
"Bracelet drop not detected": "沒檢測到手環掉入取貨斗",
"Bracelet scan failed": "沒掃碼到手環",
"Branch": "分倉",
@ -263,6 +270,7 @@
"Cannot delete role with active users.": "無法刪除已有綁定帳號的角色。",
"Cannot delete warehouse with existing stock": "無法刪除仍有庫存的倉庫",
"Card Machine System": "刷卡機系統",
"Card Payment": "卡片支付",
"Card Reader": "刷卡機",
"Card Reader No": "刷卡機編號",
"Card Reader Reboot": "刷卡機重啟",
@ -273,9 +281,10 @@
"Card Terminal": "刷卡機端",
"Card Terminal System": "刷卡機系統",
"Card UID": "卡片 UID",
"Cash Module": "硬幣機 / 紙鈔機模組",
"Cash Module": "現金模組",
"Cash Module Feature": "現金模組功能",
"Cash Module Function": "現金模組功能",
"Cash Payment": "現金支付",
"Category": "類別",
"Category Management": "分類管理",
"Category Name": "分類名稱",
@ -312,7 +321,13 @@
"Close Panel": "關閉面板",
"Code": "代碼",
"Code Copied": "代碼已複製",
"Coin": "幣",
"Coin 1": "收幣面額1",
"Coin 10": "收幣面額10",
"Coin 5": "收幣面額5",
"Coin 50": "收幣面額50",
"Coin Acceptor": "硬幣機",
"Coin Denominations": "收幣面額",
"Coin/Banknote Machine": "硬幣機/紙鈔機",
"Coin/Bill Acceptor": "硬幣機/紙鈔機",
"Command Center": "指令中心",
@ -418,6 +433,7 @@
"Creator": "建立者",
"Credit Card": "信用卡",
"Credit Card / Contactless": "支援信用卡 / 感應支付",
"Credit Card Payment": "信用卡支付",
"Critical": "嚴重",
"Critical failures requiring immediate hands-on attention.": "需要立即處理的關鍵故障。",
"Cross-Company / Headquarter Global Stats": "跨公司 / 總部全域統計",
@ -581,16 +597,18 @@
"During OTA deployment, the device will install directly in the background without user confirmation.": "未來執行 OTA 部署時,機台將跳過詢問並直接自動安裝(靜默安裝)。",
"E-Ticket (EasyCard/iPass)": "電子票證 (悠遊卡/一卡通)",
"E.SUN Bank Scan": "玉山銀行掃碼",
"E.SUN Pay": "玉山 Pay",
"E.SUN Pay": "玉山支付",
"E.SUN QR Pay": "玉山銀行掃碼",
"E.SUN QR Scan": "玉山銀行標籤支付",
"E.SUN QR Scan": "玉山掃碼",
"E.SUN QR Scan Settings Description": "玉山銀行掃碼支付設定",
"EASY_MERCHANT_ID": "悠遊付 商店代號",
"EASY_MERCHANT_ID": "EASY_MERCHANT_ID (悠遊付)",
"ECPay Invoice": "綠界電子發票",
"ECPay Invoice Settings Description": "綠界科技電子發票設定",
"ESUN": "玉山銀行",
"ESUN Scan Pay": "玉山掃碼支付",
"Easy Wallet": "悠遊付",
"EasyCard": "悠遊卡",
"EasyWallet": "悠遊付",
"Edit": "編輯",
"Edit Account": "編輯帳號",
"Edit Advertisement": "編輯廣告",
@ -604,6 +622,7 @@
"Edit Machine Model": "編輯機台型號",
"Edit Machine Name": "編輯機台名稱",
"Edit Machine Settings": "編輯機台設定",
"Edit Machine System Settings": "編輯機台系統設定",
"Edit Name": "編輯名稱",
"Edit Pass Code": "編輯通行碼",
"Edit Payment Config": "編輯金流配置",
@ -893,7 +912,7 @@
"Imported with errors. Please check the console.": "部分資料匯入失敗,請查看瀏覽器主控台。",
"In Stock": "當前庫存",
"Inactive": "已停用",
"Includes Credit Card/Mobile Pay": "含信用卡/行動支付",
"Includes Credit Card/Mobile Pay": "刷卡機支付",
"Indefinite": "無限期",
"Info": "一般",
"Inherit": "繼承",
@ -915,16 +934,21 @@
"Inventory Stable": "庫存穩定",
"Inventory synced with machine": "庫存已與機台同步",
"Invoice Date": "開立日期",
"Invoice HashIV": "發票HashIV",
"Invoice HashKey": "發票HashKey",
"Invoice Information": "發票資訊",
"Invoice Notification Email": "發票通知 Email",
"Invoice Number": "發票號碼",
"Invoice Number / Flow ID": "發票號碼 / 流水號",
"Invoice Number / Time": "發票號碼 / 時間",
"Invoice Status": "發票開立狀態",
"Invoice Store ID": "發票商店代號",
"Issued At": "開立時間",
"Item List": "商品清單",
"Items": "筆",
"JKO Pay": "街口支付",
"JKO_MERCHANT_ID": "街口支付 商店代號",
"JKOPAY": "接口支付",
"JKO_MERCHANT_ID": "JKO_MERCHANT_ID (街口支付)",
"Japanese": "日文",
"Joined": "加入日期",
"Just now": "剛剛",
@ -934,6 +958,9 @@
"LINE Pay": "LINE Pay",
"LINE Pay Direct": "LINE Pay 官方直連",
"LINE Pay Direct Settings Description": "LINE Pay 官方直連設定",
"LINE-ChannelId": "LINE-ChannelId",
"LINE-ChannelSecret": "LINE-ChannelSecret",
"LINE_MERCHANT_ID": "LINE_MERCHANT_ID (LINE Pay)",
"LINE_PAY_CHANNEL_ID": "LINE Pay 頻道 ID",
"LIVE": "實時",
"Last 7 Days": "近 7 日",
@ -960,6 +987,7 @@
"Line Members": "Line會員",
"Line Official Account": "Line生活圈",
"Line Orders": "Line訂單",
"Line Pay": "Line pay",
"Line Permissions": "Line 管理權限",
"Line Products": "Line商品",
"LinePay": "LinePay",
@ -1174,6 +1202,7 @@
"Microwave push rod retract error (0223)": "微波爐內推桿收回錯誤",
"Milk dispense timeout": "按鍵出奶超時",
"Min 8 characters": "至少 8 個字元",
"Mobile Payment": "手機支付",
"Model": "機台型號",
"Model Default": "型號預設",
"Model Name": "型號名稱",
@ -1389,12 +1418,12 @@
"Overall Capacity": "總庫存量",
"Owner": "公司名稱",
"PARTNER_KEY": "PARTNER_KEY",
"PI_MERCHANT_ID": "Pi 拍錢包 商店代號",
"PI_MERCHANT_ID": "PI_MERCHANT_ID (Pi 拍錢包)",
"PNG, JPG up to 2MB": "支援 PNG, JPG (最大 2MB)",
"PNG, JPG, WEBP up to 10MB": "支援 PNG, JPG, WEBP 格式,且不超過 10MB",
"POS Reboot": "刷卡重啟",
"PS_LEVEL": "PS_LEVEL",
"PS_MERCHANT_ID": "全盈+Pay 商店代號",
"PS_MERCHANT_ID": "PS_MERCHANT_ID (全盈+Pay)",
"Page 0": "離線",
"Page 1": "主頁面",
"Page 2": "販賣頁",
@ -1430,6 +1459,7 @@
"Pass code deleted.": "通行碼已刪除",
"Pass code disabled.": "通行碼已取消。",
"Pass code updated.": "通行碼已更新",
"Passcode": "通行碼",
"Password": "密碼",
"Password updated successfully.": "密碼已成功變更。",
"Payment & Invoice": "金流與發票",
@ -1459,13 +1489,16 @@
"Phone": "手機號碼",
"Photo Slot": "照片欄位",
"Pi Pay": "Pi 拍錢包",
"Pi Wallet": "PI 拍錢包",
"Picked up": "領取",
"Picked up Time": "領取時間",
"Pickup Code": "取貨碼",
"Pickup Code (8 Digits)": "取貨碼 (8 位數)",
"Pickup Codes": "取貨碼",
"Pickup Module": "取貨模組",
"Pickup Recipient (Prescription Slip)": "取物人(領藥單)",
"Pickup Recipient Info": "取物人資訊",
"Pickup Sheet (Material No.)": "取物單(物料編號)",
"Pickup Ticket": "商品領取券",
"Pickup Voucher": "取物單",
"Pickup code cancelled.": "取貨碼已取消",
@ -1502,7 +1535,7 @@
"Please select an APK file to upload": "請選擇要上傳的 APK 檔案",
"Please select warehouse and machine": "請選擇倉庫和機台",
"Please use our standard template to ensure data compatibility.": "請使用標準範例檔以確保資料相容性。",
"PlusPay": "全盈+PAY",
"PlusPay": "全盈+Pay",
"Point Rules": "點數規則",
"Point Settings": "點數設定",
"Points": "點數功能",
@ -1717,8 +1750,12 @@
"Saved.": "已儲存",
"Saving...": "儲存中...",
"Scale level and access control": "層級與存取控制",
"Scan Key": "掃碼Key",
"Scan Pay": "掃碼支付功能",
"Scan Payment": "掃碼支付",
"Scan QR Code": "掃描 QR Code",
"Scan Store ID": "掃碼StoreID",
"Scan Term ID": "掃碼TermID",
"Scan this code at the machine or share the link with the customer.": "請在機台掃描此碼,或將連結分享給客戶。",
"Scan this code at the machine to authorize testing or maintenance.": "請在機台上掃描此 QR Code 以進行測試或維護授權。",
"Scan this code to quickly access the maintenance form for this device.": "掃描此 QR Code 即可快速進入此設備的維修單填寫頁面。",
@ -1753,6 +1790,7 @@
"Search customers...": "搜尋客戶...",
"Search logs...": "搜尋紀錄...",
"Search machine name or SN...": "搜尋機台名稱或序號...",
"Search machine name or code...": "搜尋機台名稱或代號...",
"Search machine name, S/N, or location...": "搜尋機台名稱、序號 (S/N) 或位置...",
"Search machine name, serial no...": "搜尋機台名稱、編號...",
"Search machines by name or serial...": "搜尋機台名稱或序號...",
@ -1774,6 +1812,7 @@
"Security & State": "安全性與狀態",
"Security Controls": "安全控制",
"Select All": "全選",
"Select All / Deselect All": "全選/取消全選",
"Select Cargo Lane": "選擇貨道",
"Select Category": "選擇類別",
"Select Company": "選擇公司",
@ -1825,7 +1864,7 @@
"Setup Brand": "設定樣式",
"Shopping Cart": "購物車",
"Shopping Cart Feature": "購物車功能",
"Shopping Cart Function": "購物車功能",
"Shopping Mode": "購物方式",
"Show": "顯示",
"Show material code field in products": "在商品資料中顯示物料編號欄位",
"Show points rules in products": "在商品資料中顯示點數規則相關欄位",
@ -1984,6 +2023,7 @@
"System super admin accounts cannot be modified via this interface.": "系統超級管理員帳號無法透過此介面修改。",
"Systems Initializing": "系統初始化中",
"Table View": "列表視圖",
"TapPay": "TapPay",
"TapPay Integration": "TapPay 支付串接",
"TapPay Integration Settings Description": "喬睿科技支付串接設定",
"Target": "目標",
@ -2252,7 +2292,6 @@
"Welcome Gift Code": "來店禮代碼",
"Welcome Gift Code (8 Digits)": "來店禮代碼 (8位數)",
"Welcome Gift Feature": "迎賓禮功能",
"Welcome Gift Function": "迎賓禮功能",
"Welcome Gift Name": "來店禮名稱",
"Welcome Gift Status": "來店禮",
"Welcome Gifts": "來店禮",
@ -2342,6 +2381,8 @@
"fanon": "風扇開",
"files selected": "個檔案已選擇",
"hours ago": "小時前",
"iPASS": "一卡通",
"icash": "icash",
"image": "圖片",
"image_url": "商品圖片",
"info": "一般",
@ -2472,5 +2513,6 @@
"video": "影片",
"visit_gift": "來店禮",
"vs Yesterday": "較昨日",
"warning": "警告"
"warning": "警告",
"LINE Official Pay": "Line官方支付"
}

View File

@ -363,56 +363,6 @@
@endforeach
</x-searchable-select>
</div>
<div>
<label class="block text-xs font-bold text-slate-400 uppercase tracking-[0.15em] mb-2">{{ __('Invoice Status') }}</label>
<x-searchable-select
name="invoice_status"
:selected="old('invoice_status', $machine->invoice_status)"
:hasSearch="false"
>
<option value="0" {{ $machine->invoice_status == 0 ? 'selected' : '' }}>{{ __('No Invoice') }}</option>
<option value="1" {{ $machine->invoice_status == 1 ? 'selected' : '' }}>{{ __('Default Donate') }}</option>
<option value="2" {{ $machine->invoice_status == 2 ? 'selected' : '' }}>{{ __('Default Not Donate') }}</option>
</x-searchable-select>
</div>
</div>
</div>
<div class="luxury-card rounded-3xl p-8 animate-luxury-in relative z-10" style="animation-delay: 300ms">
<div class="flex items-center gap-3 mb-8">
<div class="w-10 h-10 rounded-xl bg-indigo-500/10 flex items-center justify-center text-indigo-500">
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/>
</svg>
</div>
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight">{{ __('Member & External') }}</h3>
</div>
<div class="space-y-6">
<label class="flex items-center justify-between p-4 rounded-2xl border border-slate-100 dark:border-slate-800 bg-slate-50/30 dark:bg-slate-900/30 cursor-pointer group">
<div>
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-indigo-500 transition-colors">{{ __('Welcome Gift') }}</span>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Enabled/Disabled') }}</span>
</div>
<div class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="welcome_gift_enabled" value="0">
<input type="checkbox" name="welcome_gift_enabled" value="1" {{ $machine->welcome_gift_enabled ? 'checked' : '' }} class="sr-only peer">
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-indigo-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-500 transition-colors"></div>
</div>
</label>
<label class="flex items-center justify-between p-4 rounded-2xl border border-slate-100 dark:border-slate-800 bg-slate-50/30 dark:bg-slate-900/30 cursor-pointer group">
<div>
<span class="block text-sm font-black text-slate-700 dark:text-slate-200 group-hover:text-indigo-500 transition-colors">{{ __('Member System') }}</span>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">{{ __('Enabled/Disabled') }}</span>
</div>
<div class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="member_system_enabled" value="0">
<input type="checkbox" name="member_system_enabled" value="1" {{ $machine->member_system_enabled ? 'checked' : '' }} class="sr-only peer">
<div class="w-11 h-6 bg-slate-200 dark:bg-slate-700 rounded-full peer peer-focus:ring-4 peer-focus:ring-indigo-500/20 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-indigo-500 transition-colors"></div>
</div>
</label>
</div>
</div>

View File

@ -99,19 +99,99 @@
machineSettings: {},
openMachineSettingsModal(machine) {
this.currentMachine = machine;
const settings = machine.settings || {};
this.machineSettings = {
shopping_mode: settings.shopping_mode || 'basic',
tax_invoice_enabled: machine.tax_invoice_enabled === true || machine.tax_invoice_enabled === 1 || machine.tax_invoice_enabled === '1',
// 刷卡機支付
card_terminal_enabled: machine.card_terminal_enabled === true || machine.card_terminal_enabled === 1 || machine.card_terminal_enabled === '1',
credit_card_enabled: settings.credit_card_enabled === true || settings.credit_card_enabled === 1 || settings.credit_card_enabled === '1',
mobile_pay_enabled: settings.mobile_pay_enabled === true || settings.mobile_pay_enabled === 1 || settings.mobile_pay_enabled === '1',
card_pay_enabled: settings.card_pay_enabled === true || settings.card_pay_enabled === 1 || settings.card_pay_enabled === '1',
// 掃碼支付
scan_pay_enabled: settings.scan_pay_enabled === true || settings.scan_pay_enabled === 1 || settings.scan_pay_enabled === '1',
scan_pay_esun_enabled: machine.scan_pay_esun_enabled === true || machine.scan_pay_esun_enabled === 1 || machine.scan_pay_esun_enabled === '1',
scan_pay_linepay_enabled: machine.scan_pay_linepay_enabled === true || machine.scan_pay_linepay_enabled === 1 || machine.scan_pay_linepay_enabled === '1',
scan_pay_tappay_enabled: settings.scan_pay_tappay_enabled === true || settings.scan_pay_tappay_enabled === 1 || settings.scan_pay_tappay_enabled === '1',
tappay_linepay: settings.tappay_linepay === true || settings.tappay_linepay === 1 || settings.tappay_linepay === '1',
tappay_jkopay: settings.tappay_jkopay === true || settings.tappay_jkopay === 1 || settings.tappay_jkopay === '1',
tappay_pipay: settings.tappay_pipay === true || settings.tappay_pipay === 1 || settings.tappay_pipay === '1',
tappay_pluspay: settings.tappay_pluspay === true || settings.tappay_pluspay === 1 || settings.tappay_pluspay === '1',
tappay_easywallet: settings.tappay_easywallet === true || settings.tappay_easywallet === 1 || settings.tappay_easywallet === '1',
// Line 官方支付 (LINE Pay 官方直連)
scan_pay_linepay_enabled: settings.scan_pay_linepay_enabled === true || settings.scan_pay_linepay_enabled === 1 || settings.scan_pay_linepay_enabled === '1',
// 現金支付 (預設皆可收,若 JSON 中特別記錄 false 才是 false)
cash_module_enabled: machine.cash_module_enabled === true || machine.cash_module_enabled === 1 || machine.cash_module_enabled === '1',
cash_bill_1000: settings.cash_bill_1000 !== false && settings.cash_bill_1000 !== 0 && settings.cash_bill_1000 !== '0',
cash_bill_500: settings.cash_bill_500 !== false && settings.cash_bill_500 !== 0 && settings.cash_bill_500 !== '0',
cash_bill_100: settings.cash_bill_100 !== false && settings.cash_bill_100 !== 0 && settings.cash_bill_100 !== '0',
cash_coin_50: settings.cash_coin_50 !== false && settings.cash_coin_50 !== 0 && settings.cash_coin_50 !== '0',
cash_coin_10: settings.cash_coin_10 !== false && settings.cash_coin_10 !== 0 && settings.cash_coin_10 !== '0',
cash_coin_5: settings.cash_coin_5 !== false && settings.cash_coin_5 !== 0 && settings.cash_coin_5 !== '0',
cash_coin_1: settings.cash_coin_1 !== false && settings.cash_coin_1 !== 0 && settings.cash_coin_1 !== '0',
// 取貨模組
pickup_module_enabled: settings.pickup_module_enabled !== undefined
? (settings.pickup_module_enabled === true || settings.pickup_module_enabled === 1 || settings.pickup_module_enabled === '1')
: ((settings.pickup_code_enabled === true || settings.pickup_code_enabled === 1 || settings.pickup_code_enabled === '1') || (settings.pass_code_enabled === true || settings.pass_code_enabled === 1 || settings.pass_code_enabled === '1')),
pickup_code_enabled: settings.pickup_code_enabled === true || settings.pickup_code_enabled === 1 || settings.pickup_code_enabled === '1',
pass_code_enabled: settings.pass_code_enabled === true || settings.pass_code_enabled === 1 || settings.pass_code_enabled === '1',
// 零售附加功能
shopping_cart_enabled: machine.shopping_cart_enabled === true || machine.shopping_cart_enabled === 1 || machine.shopping_cart_enabled === '1',
welcome_gift_enabled: machine.welcome_gift_enabled === true || machine.welcome_gift_enabled === 1 || machine.welcome_gift_enabled === '1',
cash_module_enabled: machine.cash_module_enabled === true || machine.cash_module_enabled === 1 || machine.cash_module_enabled === '1',
member_system_enabled: machine.member_system_enabled === true || machine.member_system_enabled === 1 || machine.member_system_enabled === '1',
// 環境監控
ambient_temp_monitoring_enabled: machine.ambient_temp_monitoring_enabled === true || machine.ambient_temp_monitoring_enabled === 1 || machine.ambient_temp_monitoring_enabled === '1'
};
this.showMachineSettingsModal = true;
},
toggleAllCardTerminal() {
const keys = ['credit_card_enabled', 'mobile_pay_enabled', 'card_pay_enabled'];
const allChecked = keys.every(k => this.machineSettings[k]);
keys.forEach(k => {
this.machineSettings[k] = !allChecked;
});
},
toggleAllScanPay() {
const keys = ['scan_pay_esun_enabled', 'scan_pay_tappay_enabled', 'tappay_linepay', 'tappay_jkopay', 'tappay_pipay', 'tappay_pluspay', 'tappay_easywallet'];
const allChecked = keys.every(k => this.machineSettings[k]);
keys.forEach(k => {
this.machineSettings[k] = !allChecked;
});
},
toggleAllCash() {
const keys = ['cash_bill_1000', 'cash_bill_500', 'cash_bill_100', 'cash_coin_50', 'cash_coin_10', 'cash_coin_5', 'cash_coin_1'];
const allChecked = keys.every(k => this.machineSettings[k]);
keys.forEach(k => {
this.machineSettings[k] = !allChecked;
});
},
toggleAllPickup() {
const keys = ['pickup_code_enabled', 'pass_code_enabled'];
const allChecked = keys.every(k => this.machineSettings[k]);
keys.forEach(k => {
this.machineSettings[k] = !allChecked;
});
},
toggleAllPayments() {
const mainKeys = ['card_terminal_enabled', 'scan_pay_enabled', 'scan_pay_linepay_enabled', 'cash_module_enabled', 'pickup_module_enabled'];
const subKeys = [
'credit_card_enabled', 'mobile_pay_enabled', 'card_pay_enabled',
'scan_pay_esun_enabled', 'scan_pay_tappay_enabled', 'tappay_linepay', 'tappay_jkopay', 'tappay_pipay', 'tappay_pluspay', 'tappay_easywallet',
'cash_bill_1000', 'cash_bill_500', 'cash_bill_100', 'cash_coin_50', 'cash_coin_10', 'cash_coin_5', 'cash_coin_1',
'pickup_code_enabled', 'pass_code_enabled'
];
const allMainChecked = mainKeys.every(k => this.machineSettings[k]);
const targetValue = !allMainChecked;
mainKeys.forEach(k => this.machineSettings[k] = targetValue);
subKeys.forEach(k => this.machineSettings[k] = targetValue);
},
openMaintenanceQr(machine) {
this.maintenanceQrMachineName = machine.name;
const baseUrl = '{{ route('admin.maintenance.create', ['serial_no' => 'SERIAL_NO']) }}';
@ -437,9 +517,308 @@
@method('PATCH')
<div class="space-y-3">
<!-- 稅務系統 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<!-- 購物方式 (單選) -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Shopping Mode') }}</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="settings[shopping_mode]" value="basic" x-model="machineSettings.shopping_mode" class="w-4 h-4 text-cyan-500 border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Basic Mode') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="settings[shopping_mode]" value="employee_card" x-model="machineSettings.shopping_mode" class="w-4 h-4 text-cyan-500 border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Staff Card') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="settings[shopping_mode]" value="pickup_sheet" x-model="machineSettings.shopping_mode" class="w-4 h-4 text-cyan-500 border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Pickup Sheet (Material No.)') }}</span>
</label>
</div>
</div>
<!-- 零售/金流展開部分 (僅基礎版顯示) -->
<div x-show="machineSettings.shopping_mode === 'basic'" x-transition class="space-y-3 rounded-2xl border border-slate-200 dark:border-slate-700/60 border-l-4 border-l-cyan-500 bg-slate-50/40 dark:bg-slate-800/20 p-4">
<!-- 基礎版專屬區塊標籤 -->
<div class="flex items-center">
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black uppercase tracking-wider">
<svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
</svg>
{{ __('Basic Mode Features') }}
</span>
</div>
<!-- 一鍵全選/取消全選所有金流 -->
<div class="flex justify-between items-center px-4 py-3 rounded-xl bg-slate-50/50 dark:bg-slate-800/30 border border-slate-100 dark:border-slate-800">
<span class="text-xs font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest">{{ __('Payment Type') }}</span>
<button type="button" @click="toggleAllPayments()" class="text-xs font-bold text-cyan-500 hover:text-cyan-600 transition-colors uppercase tracking-wider">
{{ __('Select All / Deselect All') }}
</button>
</div>
<!-- 刷卡機支付 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Includes Credit Card/Mobile Pay') }}</h4>
<button type="button" x-show="machineSettings.card_terminal_enabled" x-transition @click="toggleAllCardTerminal()" class="text-[10px] font-bold text-cyan-500 hover:text-cyan-600 transition-colors uppercase tracking-wider">
{{ __('Select All / Deselect All') }}
</button>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[card_terminal_enabled]" value="0">
<input type="checkbox" name="settings[card_terminal_enabled]" value="1"
x-model="machineSettings.card_terminal_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
<!-- 刷卡機子項目 -->
<div x-show="machineSettings.card_terminal_enabled" x-transition class="pl-4 border-l-2 border-slate-200 dark:border-slate-700 space-y-3">
<div class="flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[credit_card_enabled]" value="0">
<input type="checkbox" name="settings[credit_card_enabled]" value="1" x-model="machineSettings.credit_card_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Credit Card Payment') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[mobile_pay_enabled]" value="0">
<input type="checkbox" name="settings[mobile_pay_enabled]" value="1" x-model="machineSettings.mobile_pay_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Mobile Payment') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[card_pay_enabled]" value="0">
<input type="checkbox" name="settings[card_pay_enabled]" value="1" x-model="machineSettings.card_pay_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Card Payment') }}</span>
</label>
</div>
</div>
</div>
<!-- 掃碼支付 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Scan Payment') }}</h4>
<button type="button" x-show="machineSettings.scan_pay_enabled" x-transition @click="toggleAllScanPay()" class="text-[10px] font-bold text-cyan-500 hover:text-cyan-600 transition-colors uppercase tracking-wider">
{{ __('Select All / Deselect All') }}
</button>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[scan_pay_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_enabled]" value="1"
x-model="machineSettings.scan_pay_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
<!-- 掃碼子項目 -->
<div x-show="machineSettings.scan_pay_enabled" x-transition class="pl-4 border-l-2 border-slate-200 dark:border-slate-700 space-y-3">
<div class="flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[scan_pay_esun_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_esun_enabled]" value="1" x-model="machineSettings.scan_pay_esun_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('E.SUN Pay') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[scan_pay_tappay_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_tappay_enabled]" value="1" x-model="machineSettings.scan_pay_tappay_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('TapPay') }}</span>
</label>
</div>
<!-- TapPay 孫項目 -->
<div x-show="machineSettings.scan_pay_tappay_enabled && machineSettings.scan_pay_enabled" x-transition class="pl-4 border-l border-dashed border-slate-200 dark:border-slate-700 flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[tappay_linepay]" value="0">
<input type="checkbox" name="settings[tappay_linepay]" value="1" x-model="machineSettings.tappay_linepay" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Line Pay') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[tappay_jkopay]" value="0">
<input type="checkbox" name="settings[tappay_jkopay]" value="1" x-model="machineSettings.tappay_jkopay" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('JKOPAY') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[tappay_pipay]" value="0">
<input type="checkbox" name="settings[tappay_pipay]" value="1" x-model="machineSettings.tappay_pipay" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Pi Wallet') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[tappay_pluspay]" value="0">
<input type="checkbox" name="settings[tappay_pluspay]" value="1" x-model="machineSettings.tappay_pluspay" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('PlusPay') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[tappay_easywallet]" value="0">
<input type="checkbox" name="settings[tappay_easywallet]" value="1" x-model="machineSettings.tappay_easywallet" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('EasyWallet') }}</span>
</label>
</div>
</div>
</div>
<!-- Line 官方支付 (LINE Pay 官方直連) -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="flex items-center justify-between">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('LINE Official Pay') }}</h4>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[scan_pay_linepay_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_linepay_enabled]" value="1"
x-model="machineSettings.scan_pay_linepay_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
</div>
<!-- 現金支付 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Cash Payment') }}</h4>
<button type="button" x-show="machineSettings.cash_module_enabled" x-transition @click="toggleAllCash()" class="text-[10px] font-bold text-cyan-500 hover:text-cyan-600 transition-colors uppercase tracking-wider">
{{ __('Select All / Deselect All') }}
</button>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[cash_module_enabled]" value="0">
<input type="checkbox" name="settings[cash_module_enabled]" value="1"
x-model="machineSettings.cash_module_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
<!-- 現金面額子項目 -->
<div x-show="machineSettings.cash_module_enabled" x-transition class="pl-4 border-l-2 border-slate-200 dark:border-slate-700 space-y-3">
<div>
<span class="text-xs font-black text-slate-400 uppercase tracking-widest block mb-2">{{ __('Bill Denominations') }}</span>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_bill_1000]" value="0">
<input type="checkbox" name="settings[cash_bill_1000]" value="1" x-model="machineSettings.cash_bill_1000" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">1000</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_bill_500]" value="0">
<input type="checkbox" name="settings[cash_bill_500]" value="1" x-model="machineSettings.cash_bill_500" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">500</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_bill_100]" value="0">
<input type="checkbox" name="settings[cash_bill_100]" value="1" x-model="machineSettings.cash_bill_100" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">100</span>
</label>
</div>
</div>
<div class="pt-2">
<span class="text-xs font-black text-slate-400 uppercase tracking-widest block mb-2">{{ __('Coin Denominations') }}</span>
<div class="flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_coin_50]" value="0">
<input type="checkbox" name="settings[cash_coin_50]" value="1" x-model="machineSettings.cash_coin_50" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">50</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_coin_10]" value="0">
<input type="checkbox" name="settings[cash_coin_10]" value="1" x-model="machineSettings.cash_coin_10" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">10</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_coin_5]" value="0">
<input type="checkbox" name="settings[cash_coin_5]" value="1" x-model="machineSettings.cash_coin_5" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">5</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[cash_coin_1]" value="0">
<input type="checkbox" name="settings[cash_coin_1]" value="1" x-model="machineSettings.cash_coin_1" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">1</span>
</label>
</div>
</div>
</div>
</div>
<!-- 取貨模組 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors space-y-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Pickup Module') }}</h4>
<button type="button" x-show="machineSettings.pickup_module_enabled" x-transition @click="toggleAllPickup()" class="text-[10px] font-bold text-cyan-500 hover:text-cyan-600 transition-colors uppercase tracking-wider">
{{ __('Select All / Deselect All') }}
</button>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[pickup_module_enabled]" value="0">
<input type="checkbox" name="settings[pickup_module_enabled]" value="1"
x-model="machineSettings.pickup_module_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
<div x-show="machineSettings.pickup_module_enabled" x-transition class="pl-4 border-l-2 border-slate-200 dark:border-slate-700 flex flex-wrap gap-x-6 gap-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[pickup_code_enabled]" value="0">
<input type="checkbox" name="settings[pickup_code_enabled]" value="1" x-model="machineSettings.pickup_code_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Pickup Code') }}</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="hidden" name="settings[pass_code_enabled]" value="0">
<input type="checkbox" name="settings[pass_code_enabled]" value="1" x-model="machineSettings.pass_code_enabled" class="w-4 h-4 text-cyan-500 rounded border-slate-300 focus:ring-cyan-500 dark:bg-slate-800 dark:border-slate-700 dark:checked:bg-cyan-500 dark:checked:border-cyan-500 dark:focus:border-cyan-500">
<span class="text-xs font-bold text-slate-600 dark:text-slate-300">{{ __('Passcode') }}</span>
</label>
</div>
</div>
<!-- 購物車功能 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="flex items-center justify-between">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Shopping Cart') }}</h4>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[shopping_cart_enabled]" value="0">
<input type="checkbox" name="settings[shopping_cart_enabled]" value="1"
x-model="machineSettings.shopping_cart_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
</div>
<!-- 來店禮功能 -->
<div class="p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="flex items-center justify-between">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Welcome Gift') }}</h4>
<label class="relative inline-flex items-center cursor-pointer">
<input type="hidden" name="settings[welcome_gift_enabled]" value="0">
<input type="checkbox" name="settings[welcome_gift_enabled]" value="1"
x-model="machineSettings.welcome_gift_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</label>
</div>
</div>
</div>
<!-- 會員系統功能 -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Member System') }}</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[member_system_enabled]" value="0">
<input type="checkbox" name="settings[member_system_enabled]" value="1"
x-model="machineSettings.member_system_enabled" class="peer sr-only">
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</div>
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Member System') }}</span>
</label>
</div>
</div>
<!-- 稅務系統 (電子發票) -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Tax System') }}</h4>
</div>
@ -449,176 +828,15 @@
<input type="hidden" name="settings[tax_invoice_enabled]" value="0">
<input type="checkbox" name="settings[tax_invoice_enabled]" value="1"
x-model="machineSettings.tax_invoice_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('Electronic Invoice') }}</span>
</label>
</div>
</div>
<!-- 刷卡機系統 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Card Machine System') }}</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[card_terminal_enabled]" value="0">
<input type="checkbox" name="settings[card_terminal_enabled]" value="1"
x-model="machineSettings.card_terminal_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('Includes Credit Card/Mobile Pay') }}</span>
</label>
</div>
</div>
<!-- 掃碼支付功能 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Scan Pay')
}}</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[scan_pay_esun_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_esun_enabled]" value="1"
x-model="machineSettings.scan_pay_esun_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('E.SUN QR Pay') }}</span>
</label>
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[scan_pay_linepay_enabled]" value="0">
<input type="checkbox" name="settings[scan_pay_linepay_enabled]" value="1"
x-model="machineSettings.scan_pay_linepay_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('LinePay Payment') }}</span>
</label>
</div>
</div>
<!-- 購物車功能 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('購物車功能') }}
</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[shopping_cart_enabled]" value="0">
<input type="checkbox" name="settings[shopping_cart_enabled]" value="1"
x-model="machineSettings.shopping_cart_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('購物車') }}</span>
</label>
</div>
</div>
<!-- 來店禮功能 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('來店禮功能') }}
</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[welcome_gift_enabled]" value="0">
<input type="checkbox" name="settings[welcome_gift_enabled]" value="1"
x-model="machineSettings.welcome_gift_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('來店禮') }}</span>
</label>
</div>
</div>
<!-- 現金模組功能 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('現金模組功能') }}
</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[cash_module_enabled]" value="0">
<input type="checkbox" name="settings[cash_module_enabled]" value="1"
x-model="machineSettings.cash_module_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('硬幣機/紙鈔機') }}</span>
</label>
</div>
</div>
<!-- 會員系統 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('會員系統功能') }}
</h4>
</div>
<div class="md:col-span-3 flex flex-wrap gap-x-8 gap-y-4">
<label class="flex items-center gap-3 cursor-pointer group">
<div class="relative inline-flex items-center">
<input type="hidden" name="settings[member_system_enabled]" value="0">
<input type="checkbox" name="settings[member_system_enabled]" value="1"
x-model="machineSettings.member_system_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('會員系統') }}</span>
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Electronic Invoice') }}</span>
</label>
</div>
</div>
<!-- 硬體周邊設定 -->
<div
class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 items-center p-4 rounded-xl bg-slate-50/50 dark:bg-slate-800/50 border border-slate-100 dark:border-slate-700/50 hover:bg-slate-50 dark:hover:bg-slate-800 transition-colors">
<div class="md:col-span-1">
<h4 class="text-sm font-black text-slate-700 dark:text-slate-200">{{ __('Hardware Peripheral Settings') }}</h4>
</div>
@ -628,13 +846,9 @@
<input type="hidden" name="settings[ambient_temp_monitoring_enabled]" value="0">
<input type="checkbox" name="settings[ambient_temp_monitoring_enabled]" value="1"
x-model="machineSettings.ambient_temp_monitoring_enabled" class="peer sr-only">
<div
class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500">
</div>
<div class="w-9 h-5 bg-slate-200 peer-focus:outline-none rounded-full peer dark:bg-slate-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-cyan-500"></div>
</div>
<span
class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{
__('Ambient Temperature Monitoring') }}</span>
<span class="text-sm font-bold text-slate-600 dark:text-slate-300 group-hover:text-slate-900 dark:group-hover:text-white transition-colors">{{ __('Ambient Temperature Monitoring') }}</span>
</label>
</div>
</div>

View File

@ -11,7 +11,7 @@
</span>
<input type="text" x-model="machineSearch" @input.debounce.500ms="searchInTab('system_settings')"
@keydown.enter.prevent="searchInTab('system_settings')"
placeholder="{{ __('搜尋機台名稱或代號...') }}"
placeholder="{{ __('Search machine name or code...') }}"
class="luxury-input py-2.5 pl-11 pr-4 block w-full sm:w-72 text-sm font-bold">
</div>
@ -84,13 +84,87 @@
@forelse($machines as $machine)
@php
$activeFeatures = [];
if ($machine->tax_invoice_enabled) $activeFeatures[] = __('Electronic Invoice');
if ($machine->card_terminal_enabled) $activeFeatures[] = __('Includes Credit Card/Mobile Pay');
if ($machine->scan_pay_esun_enabled) $activeFeatures[] = __('E.SUN Bank Scan');
if ($machine->scan_pay_linepay_enabled) $activeFeatures[] = __('LinePay Payment');
if ($machine->shopping_cart_enabled) $activeFeatures[] = __('Shopping Cart');
if ($machine->welcome_gift_enabled) $activeFeatures[] = __('Welcome Gift');
if ($machine->cash_module_enabled) $activeFeatures[] = __('Coin/Banknote Machine');
$shoppingMode = $machine->settings['shopping_mode'] ?? 'basic';
if ($shoppingMode === 'employee_card') {
$activeFeatures[] = __('Staff Card');
} elseif ($shoppingMode === 'pickup_sheet') {
$activeFeatures[] = __('Pickup Sheet (Material No.)');
} else {
$activeFeatures[] = __('Basic Mode');
if ($machine->tax_invoice_enabled) $activeFeatures[] = __('Electronic Invoice');
if ($machine->card_terminal_enabled) {
$terminals = [];
if ($machine->settings['credit_card_enabled'] ?? false) {
$terminals[] = __('Credit Card Payment');
}
if ($machine->settings['mobile_pay_enabled'] ?? false) {
$terminals[] = __('Mobile Payment');
}
if ($machine->settings['card_pay_enabled'] ?? false) {
$terminals[] = __('Card Payment');
}
if (!empty($terminals)) {
$activeFeatures[] = __('Includes Credit Card/Mobile Pay') . ' (' . implode(', ', $terminals) . ')';
} else {
$activeFeatures[] = __('Includes Credit Card/Mobile Pay');
}
}
if ($machine->settings['scan_pay_enabled'] ?? false) {
$scans = [];
if ($machine->scan_pay_esun_enabled) $scans[] = __('E.SUN Pay');
if ($machine->settings['scan_pay_tappay_enabled'] ?? false) {
$taps = [];
if ($machine->settings['tappay_linepay'] ?? false) $taps[] = __('Line Pay');
if ($machine->settings['tappay_jkopay'] ?? false) $taps[] = __('JKOPAY');
if ($machine->settings['tappay_pipay'] ?? false) $taps[] = __('Pi Wallet');
if ($machine->settings['tappay_pluspay'] ?? false) $taps[] = __('PlusPay');
if ($machine->settings['tappay_easywallet'] ?? false) $taps[] = __('EasyWallet');
if (!empty($taps)) {
$scans[] = 'TapPay (' . implode('/', $taps) . ')';
}
}
if (!empty($scans)) {
$activeFeatures[] = __('Scan Payment') . ' (' . implode(', ', $scans) . ')';
}
}
if ($machine->settings['scan_pay_linepay_enabled'] ?? false) {
$activeFeatures[] = __('LINE Official Pay');
}
if ($machine->cash_module_enabled) {
$bills = [];
if (($machine->settings['cash_bill_1000'] ?? true) !== false) $bills[] = '1000';
if (($machine->settings['cash_bill_500'] ?? true) !== false) $bills[] = '500';
if (($machine->settings['cash_bill_100'] ?? true) !== false) $bills[] = '100';
$coins = [];
if (($machine->settings['cash_coin_50'] ?? true) !== false) $coins[] = '50';
if (($machine->settings['cash_coin_10'] ?? true) !== false) $coins[] = '10';
if (($machine->settings['cash_coin_5'] ?? true) !== false) $coins[] = '5';
if (($machine->settings['cash_coin_1'] ?? true) !== false) $coins[] = '1';
$cashStr = __('Cash Module');
if (!empty($bills) || !empty($coins)) {
$cashStr .= ' (';
if (!empty($bills)) $cashStr .= __('Bill') . ':' . implode('/', $bills);
if (!empty($bills) && !empty($coins)) $cashStr .= ' ';
if (!empty($coins)) $cashStr .= __('Coin') . ':' . implode('/', $coins);
$cashStr .= ')';
}
$activeFeatures[] = $cashStr;
}
$pickups = [];
if ($machine->settings['pickup_code_enabled'] ?? false) $pickups[] = __('Pickup Code');
if ($machine->settings['pass_code_enabled'] ?? false) $pickups[] = __('Passcode');
if (!empty($pickups)) {
$activeFeatures[] = __('Pickup Module') . ' (' . implode('/', $pickups) . ')';
}
if ($machine->shopping_cart_enabled) $activeFeatures[] = __('Shopping Cart');
if ($machine->welcome_gift_enabled) $activeFeatures[] = __('Welcome Gift');
}
if ($machine->member_system_enabled) $activeFeatures[] = __('Member System');
if ($machine->ambient_temp_monitoring_enabled) $activeFeatures[] = __('Ambient Temperature Monitoring');
@endphp
@ -142,13 +216,87 @@
@forelse($machines as $machine)
@php
$activeFeatures = [];
if ($machine->tax_invoice_enabled) $activeFeatures[] = __('Electronic Invoice');
if ($machine->card_terminal_enabled) $activeFeatures[] = __('Includes Credit Card/Mobile Pay');
if ($machine->scan_pay_esun_enabled) $activeFeatures[] = __('E.SUN Bank Scan');
if ($machine->scan_pay_linepay_enabled) $activeFeatures[] = __('LinePay Payment');
if ($machine->shopping_cart_enabled) $activeFeatures[] = __('Shopping Cart');
if ($machine->welcome_gift_enabled) $activeFeatures[] = __('Welcome Gift');
if ($machine->cash_module_enabled) $activeFeatures[] = __('Coin/Banknote Machine');
$shoppingMode = $machine->settings['shopping_mode'] ?? 'basic';
if ($shoppingMode === 'employee_card') {
$activeFeatures[] = __('Staff Card');
} elseif ($shoppingMode === 'pickup_sheet') {
$activeFeatures[] = __('Pickup Sheet (Material No.)');
} else {
$activeFeatures[] = __('Basic Mode');
if ($machine->tax_invoice_enabled) $activeFeatures[] = __('Electronic Invoice');
if ($machine->card_terminal_enabled) {
$terminals = [];
if ($machine->settings['credit_card_enabled'] ?? false) {
$terminals[] = __('Credit Card Payment');
}
if ($machine->settings['mobile_pay_enabled'] ?? false) {
$terminals[] = __('Mobile Payment');
}
if ($machine->settings['card_pay_enabled'] ?? false) {
$terminals[] = __('Card Payment');
}
if (!empty($terminals)) {
$activeFeatures[] = __('Includes Credit Card/Mobile Pay') . ' (' . implode(', ', $terminals) . ')';
} else {
$activeFeatures[] = __('Includes Credit Card/Mobile Pay');
}
}
if ($machine->settings['scan_pay_enabled'] ?? false) {
$scans = [];
if ($machine->scan_pay_esun_enabled) $scans[] = __('E.SUN Pay');
if ($machine->settings['scan_pay_tappay_enabled'] ?? false) {
$taps = [];
if ($machine->settings['tappay_linepay'] ?? false) $taps[] = __('Line Pay');
if ($machine->settings['tappay_jkopay'] ?? false) $taps[] = __('JKOPAY');
if ($machine->settings['tappay_pipay'] ?? false) $taps[] = __('Pi Wallet');
if ($machine->settings['tappay_pluspay'] ?? false) $taps[] = __('PlusPay');
if ($machine->settings['tappay_easywallet'] ?? false) $taps[] = __('EasyWallet');
if (!empty($taps)) {
$scans[] = 'TapPay (' . implode('/', $taps) . ')';
}
}
if (!empty($scans)) {
$activeFeatures[] = __('Scan Payment') . ' (' . implode(', ', $scans) . ')';
}
}
if ($machine->settings['scan_pay_linepay_enabled'] ?? false) {
$activeFeatures[] = __('LINE Official Pay');
}
if ($machine->cash_module_enabled) {
$bills = [];
if (($machine->settings['cash_bill_1000'] ?? true) !== false) $bills[] = '1000';
if (($machine->settings['cash_bill_500'] ?? true) !== false) $bills[] = '500';
if (($machine->settings['cash_bill_100'] ?? true) !== false) $bills[] = '100';
$coins = [];
if (($machine->settings['cash_coin_50'] ?? true) !== false) $coins[] = '50';
if (($machine->settings['cash_coin_10'] ?? true) !== false) $coins[] = '10';
if (($machine->settings['cash_coin_5'] ?? true) !== false) $coins[] = '5';
if (($machine->settings['cash_coin_1'] ?? true) !== false) $coins[] = '1';
$cashStr = __('Cash Module');
if (!empty($bills) || !empty($coins)) {
$cashStr .= ' (';
if (!empty($bills)) $cashStr .= __('Bill') . ':' . implode('/', $bills);
if (!empty($bills) && !empty($coins)) $cashStr .= ' ';
if (!empty($coins)) $cashStr .= __('Coin') . ':' . implode('/', $coins);
$cashStr .= ')';
}
$activeFeatures[] = $cashStr;
}
$pickups = [];
if ($machine->settings['pickup_code_enabled'] ?? false) $pickups[] = __('Pickup Code');
if ($machine->settings['pass_code_enabled'] ?? false) $pickups[] = __('Passcode');
if (!empty($pickups)) {
$activeFeatures[] = __('Pickup Module') . ' (' . implode('/', $pickups) . ')';
}
if ($machine->shopping_cart_enabled) $activeFeatures[] = __('Shopping Cart');
if ($machine->welcome_gift_enabled) $activeFeatures[] = __('Welcome Gift');
}
if ($machine->member_system_enabled) $activeFeatures[] = __('Member System');
if ($machine->ambient_temp_monitoring_enabled) $activeFeatures[] = __('Ambient Temperature Monitoring');
@endphp

View File

@ -100,17 +100,21 @@
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Store ID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice Store ID') }}</label>
<input type="text" name="settings[ecpay_invoice][store_id]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('HashKey') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice HashKey') }}</label>
<input type="text" name="settings[ecpay_invoice][hash_key]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('HashIV') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice HashIV') }}</label>
<input type="text" name="settings[ecpay_invoice][hash_iv]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice Notification Email') }}</label>
<input type="text" name="settings[ecpay_invoice][email]" class="luxury-input w-full">
</div>
</div>
</div>
@ -127,15 +131,15 @@
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('StoreID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Store ID') }}</label>
<input type="text" name="settings[esun_scan][store_id]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('TermID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Term ID') }}</label>
<input type="text" name="settings[esun_scan][term_id]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Key') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Key') }}</label>
<input type="text" name="settings[esun_scan][key]" class="luxury-input w-full">
</div>
</div>
@ -148,17 +152,17 @@
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m24.408 0a8.959 8.959 0 0 1 .284-2.253m0 2.253C20.46 17.1 16.485 19.5 12 19.5S3.538 17.1 2.284 14.253"/></svg>
</div>
<div>
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight font-display uppercase">{{ __('LINE Pay Direct') }}</h3>
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight font-display uppercase">{{ __('LINE Official Pay') }}</h3>
</div>
</div>
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('ChannelId') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('LINE-ChannelId') }}</label>
<input type="text" name="settings[line_pay][channel_id]" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('ChannelSecret') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('LINE-ChannelSecret') }}</label>
<input type="text" name="settings[line_pay][channel_secret]" class="luxury-input w-full">
</div>
</div>

View File

@ -104,17 +104,21 @@
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Store ID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice Store ID') }}</label>
<input type="text" name="settings[ecpay_invoice][store_id]" value="{{ $settings['ecpay_invoice']['store_id'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('HashKey') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice HashKey') }}</label>
<input type="text" name="settings[ecpay_invoice][hash_key]" value="{{ $settings['ecpay_invoice']['hash_key'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('HashIV') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice HashIV') }}</label>
<input type="text" name="settings[ecpay_invoice][hash_iv]" value="{{ $settings['ecpay_invoice']['hash_iv'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Invoice Notification Email') }}</label>
<input type="text" name="settings[ecpay_invoice][email]" value="{{ $settings['ecpay_invoice']['email'] ?? '' }}" class="luxury-input w-full">
</div>
</div>
</div>
@ -131,15 +135,15 @@
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('StoreID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Store ID') }}</label>
<input type="text" name="settings[esun_scan][store_id]" value="{{ $settings['esun_scan']['store_id'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('TermID') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Term ID') }}</label>
<input type="text" name="settings[esun_scan][term_id]" value="{{ $settings['esun_scan']['term_id'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Key') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('Scan Key') }}</label>
<input type="text" name="settings[esun_scan][key]" value="{{ $settings['esun_scan']['key'] ?? '' }}" class="luxury-input w-full">
</div>
</div>
@ -152,17 +156,17 @@
<svg class="w-5 h-5 stroke-[2.5]" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m24.408 0a8.959 8.959 0 0 1 .284-2.253m0 2.253C20.46 17.1 16.485 19.5 12 19.5S3.538 17.1 2.284 14.253"/></svg>
</div>
<div>
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight font-display uppercase">{{ __('LINE Pay Direct') }}</h3>
<h3 class="text-lg font-black text-slate-800 dark:text-white tracking-tight font-display uppercase">{{ __('LINE Official Pay') }}</h3>
</div>
</div>
<div class="space-y-6">
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('ChannelId') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('LINE-ChannelId') }}</label>
<input type="text" name="settings[line_pay][channel_id]" value="{{ $settings['line_pay']['channel_id'] ?? '' }}" class="luxury-input w-full">
</div>
<div>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('ChannelSecret') }}</label>
<label class="block text-[11px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2">{{ __('LINE-ChannelSecret') }}</label>
<input type="text" name="settings[line_pay][channel_secret]" value="{{ $settings['line_pay']['channel_secret'] ?? '' }}" class="luxury-input w-full">
</div>
</div>

View File

@ -5,7 +5,7 @@
{{ $attributes->merge(['class' => 'object-contain']) }}
alt="QR Code">
@else
<img src="{{ route('admin.basic-settings.qr-code', ['data' => $data, 'size' => $size]) }}"
<img src="{{ route('qr-code.public', ['data' => $data, 'size' => $size]) }}"
{{ $attributes->merge(['class' => 'object-contain']) }}
alt="QR Code">
@endif

View File

@ -40,6 +40,9 @@ Route::get('/p/{slug}', [App\Http\Controllers\Guest\PickupController::class, 'sh
Route::get('/t/{slug}', [App\Http\Controllers\Guest\PassCodeController::class, 'show'])->name('pass-code.ticket')->middleware('throttle:60,1');
Route::get('/g/{slug}', [App\Http\Controllers\Guest\WelcomeGiftController::class, 'show'])->name('welcome-gift.ticket')->middleware('throttle:60,1');
// 公開 QR 產生 (供訪客取貨/通行/好禮頁渲染,無需登入)
Route::get('/qr-code', [App\Http\Controllers\Admin\QrCodeController::class, 'generate'])->name('qr-code.public')->middleware('throttle:120,1');
Route::get('/dashboard', function () {
return redirect()->route('admin.dashboard');
})->middleware(['auth', 'auth.session', 'verified'])->name('dashboard');