Merge remote-tracking branch 'origin/ui-design' into feat/general-cart-and-payment

This commit is contained in:
sky121113 2026-06-11 16:58:21 +08:00
commit 79e1f69325
27 changed files with 700 additions and 113 deletions

View File

@ -28,8 +28,8 @@ trigger: always_on
依據公司標準規範,實體機台發佈之 APK 與版本名稱需嚴格符合以下欄位對照:
```
來源 _ 安卓號 _ 主板號 _ 機器系列 _ 專案名稱 _ 螢幕大小 _ 次版號 _ 修補版號 _ 環境
S _ 12 _ XY _ U _ Chengwai _ 10 _ 08 _ 8 _ R
來源 _ 安卓號 _ 主板號 _ 機器系列 _ 螢幕大小 _ 次版號 _ 修補版號 _ 環境
S _ 12 _ XY _ U _ 10 _ 08 _ 8 _ R
```
### 欄位解析:
@ -37,7 +37,6 @@ S _ 12 _ XY _ U _ Chengwai _ 10 _ 08 _ 8 _ R
* **`12` (安卓號)**Android 系統主版本號。
* **`XY` (主板號)**:主板型號規格。
* **`U` (機器系列 / 機型規格)**:例如代表 U 系列機型。
* **`Chengwai` (專案名稱)**:客戶/銷售場景專案代碼(如 `General`, `Chengwai`, `Cmuh`)。
* **`10` (螢幕大小)**:對應 Gradle 中的 `verMajor`
* **`08` (次版號)**:對應 Gradle 中的 `verMinor`(格式化為雙位數)。
* **`8` (修補版號)**:對應 Gradle 中的 `verPatch`
@ -55,38 +54,32 @@ S _ 12 _ XY _ U _ Chengwai _ 10 _ 08 _ 8 _ R
---
## 4. 雙維度產品風味 (Product Flavors) 與 APK 命名規範
## 4. 單維度硬體規格 (Hardware Flavor) 與 APK 命名規範
本專案採用**雙維度 Flavor** 架構,以完美分離「客戶銷售場景」與「底層硬體規格」,方便後續快速擴充。
本專案原本採用雙維度,但目前客戶專案(購買流程)已收斂為執行期 `shopping_mode`(雲端 B014 下發)動態決定,因此不再使用 flavor 分家。
目前僅保留**單一維度 `hardware`**,專門處理底層硬體規格差異。
### 4.1 維度定義 (flavorDimensions)
本專案於 `app/build.gradle` 中定義了兩個 Flavor 維度
### 4.1 硬體維度定義 (flavorDimensions)
本專案於 `app/build.gradle` 中定義了唯一的 Flavor 維度 `hardware`
1. **`project` 維度 (客戶/銷售場景區隔)**
* **`General`** (通用主幹):預設顯示付款方式選單(彈出 `BuyDialog`)。未來新客戶最常用此通用主幹。
* **`Chengwai`** (晟崴客製):直接跳出員工卡刷卡畫面(彈出 `MemberCardPickupDialog`),不顯示付款選單。
* **`Cmuh`** (中國醫客製):支援 QR Code 掃碼、處方籤醫令離線 AES 解密與解析領藥流程。
2. **`hardware` 維度 (硬體與系統規格區隔)**
* **`S12XYU`**:代表 `S` (來源) + `12` (安卓號) + `XY` (主板號) + `U` (機器系列/機型規格)。
* **`S9XYU`**:代表中國醫現場使用的 Android 9 / 21.5 吋硬體規格;除非明確指定中國醫 10 吋或 `S12XYU`,中國醫 (`Cmuh`) 相關修正與驗證預設必須使用此硬體 flavor。
* **`S12XYU`** (10 吋預設硬體):代表 `S` (來源) + `12` (安卓號) + `XY` (主板號) + `U` (機器系列/機型規格)。
* **`S9XYU`** (21.5 吋硬體):代表中國醫現場使用的 Android 9 / 21.5 吋硬體規格。
### 4.2 Flavor 驗證與編譯指令選擇
針對特定客戶或現場問題修改後,必須編譯對應的 Gradle variant不可只用通用 `assembleDebug` 或錯誤硬體 flavor 代替。
修改後,必須編譯對應硬體規格的 Gradle variant不可只用通用 `assembleDebug`
* **中國醫現場版 (`Cmuh`) 驗證指令**`./gradlew :app:assembleCmuhS9XYUDebug --no-daemon`
* **晟崴版 (`Chengwai`) 預設驗證指令**`./gradlew :app:assembleChengwaiS12XYUDebug --no-daemon`
* **通用版 (`General`) 預設驗證指令**`./gradlew :app:assembleGeneralS12XYUDebug --no-daemon`
* **10 吋一般機台版 (含晟崴、通用等)**`./gradlew :app:assembleS12XYUDebug --no-daemon`
* **21.5 吋中國醫等大螢幕機台版**`./gradlew :app:assembleS9XYUDebug --no-daemon`
### 4.3 實體機台 APK 命名鐵律
為了符合實體機台 OTA 平台發佈規範,打包輸出的 APK 檔名必須嚴格連動雙維度,並遵循以下格式:
`app-[格式化硬體規格]_[專案名稱]-[版本號]-[BuildType].apk`
為了符合實體機台 OTA 平台發佈規範,打包輸出的 APK 檔名必須遵循以下格式:
`app-[格式化硬體規格]-[版本號]-[BuildType].apk`
* **格式化規則**`S12XYU` 會在 Gradle 打包時被自動展開格式化為 `S_12_XY_U`
* **輸出檔名範例**
* `app-S_12_XY_U_General-10_08_8_R-release.apk`
* `app-S_12_XY_U_Chengwai-10_08_8_R-release.apk`
* `app-S_12_XY_U_Cmuh-10_08_8_R-release.apk`
* `app-S_12_XY_U-10_08_8_R-release.apk`
* `app-S_9_XY_U-21_08_8_R-release.apk`
* **注意**:此檔名轉換規則已完全由 `app/build.gradle` 頂部 Gradle 變數與 `applicationVariants.all` 自動連動生成,**嚴禁手動修改輸出檔名**。
---

View File

@ -24,7 +24,8 @@
- 禁止直接手改成品 `versionCode`/`versionName` 值。
- 版號管理透過 `verMajor`、`verMinor`、`verPatch` 變數。
- OTA 發版時,`versionCode` 必須嚴格遞增。
- 中國醫現場版 (`Cmuh`) 修正預設以 `:app:assembleCmuhS9XYUDebug` 驗證。
- 21.5 吋大螢幕現場版(如中國醫)修正預設以 `:app:assembleS9XYUDebug` 驗證。
- 10 吋一般現場版(如晟崴、通用)修正預設以 `:app:assembleS12XYUDebug` 驗證。
## When Rules Conflict

View File

@ -740,6 +740,22 @@ public class FontendActivity extends AppCompatActivityAbstract implements SaleFl
binding.floatButtonShoppingCart.setVisibility(View.GONE);
}
// 觀察購物車內容以更新數量 Badge
com.unibuy.v2.UnibuyHelper.INSTANCE.getCartViewModel().getCartItems().observe(this, cartItems -> {
int totalCount = 0;
if (cartItems != null) {
for (com.unibuy.smartdevice.structure.SlotStructure item : cartItems) {
totalCount += item.cartSelectedCount;
}
}
if (totalCount > 0) {
binding.textCartBadge.setText(String.valueOf(totalCount));
binding.textCartBadge.setVisibility(View.VISIBLE);
} else {
binding.textCartBadge.setVisibility(View.GONE);
}
});
startHeaderReportScheduler();
// binding.btnswitchlanTW.setOnClickListener(v -> switchLanguage("tw"));

View File

@ -0,0 +1,148 @@
package com.unibuy.smartdevice.ui.dialog;
import android.content.Context;
import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.databinding.DialogPickupSuccessBinding;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.HandlerMainCountdown;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
import java.util.HashMap;
import java.util.Map;
public class PickupSuccessDialog extends DialogAbstract {
public enum Option {
TOAST(0),
COUNTDOWN_CANCEL(1),
SET_COUNTDOWN_TEXT(2),
RESET_COUNTDOWN(3),
;
private int option;
public int getOption() {
return option;
}
Option(int option) {
this.option = option;
}
}
public PickupSuccessDialog(Context context, HandlerMain srcHandlerMain) {
super(context, srcHandlerMain);
getLogs().info("PickupSuccessDialog:" + getClass().getSimpleName());
}
public static final Map<Integer, Option> optionMap = new HashMap<>();
static {
for (Option option : Option.values()) {
optionMap.put(option.getOption(), option);
}
}
@Override
protected Context setCtx() {
return this.getContext();
}
@Override
protected Class<? extends DialogAbstract> setCls() {
return getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getContext(), getLogs()) {
@Override
protected void execute(Context context, int commandCode, String message) {
Option option = optionMap.get(commandCode);
if (option != null) {
switch (option) {
case TOAST:
super.execute(context, commandCode, message);
break;
case COUNTDOWN_CANCEL:
cancelOnThreadCountdown();
break;
case SET_COUNTDOWN_TEXT:
setButtonConfirmText(Integer.valueOf(message));
break;
case RESET_COUNTDOWN:
closeDialogCountdown.setCountdown(15);
break;
}
}
}
};
}
private DialogPickupSuccessBinding binding;
private CloseDialogOnThreadHandler closeDialogCountdown;
private String laneNumber = "99"; // 預設貨道號碼
public void setLaneNumber(String laneNumber) {
this.laneNumber = laneNumber;
if (binding != null) {
binding.tvLaneNumber.setText(laneNumber);
binding.tvSubtitle.setText("請至" + laneNumber + "號櫃門拿取您的商品");
}
}
@Override
protected void onCreate(Context context) {
binding = DialogPickupSuccessBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 初始化貨道數字與副標文字
setLaneNumber(laneNumber);
binding.btnConfirm.setOnClickListener(v -> dialogCancel());
closeDialogCountdown = new CloseDialogOnThreadHandler(getHandlerMain());
closeDialogCountdown.start(15);
}
public void dialogCancel() {
if (closeDialogCountdown != null) {
closeDialogCountdown.shutdown();
}
cancel();
}
public void cancelOnThreadCountdown() {
getTools().dialogClose();
cancel();
}
public void setButtonConfirmText(long countdown) {
binding.btnConfirm.setText("確認已取貨(" + countdown + "秒)");
}
public static class CloseDialogOnThreadHandler extends HandlerMainCountdown {
public CloseDialogOnThreadHandler(HandlerMain handlerMain) {
super(handlerMain);
}
@Override
protected HandlerMain setHandlerMain() {
return getSrcHandlerMain();
}
@Override
protected void close(HandlerMain handlerMain) {
handlerMain.start(getClass().getSimpleName(), Option.COUNTDOWN_CANCEL.getOption(), "close dialog");
}
@Override
protected void execute(long countdown, HandlerMain handlerMain) {
handlerMain.start(getClass().getSimpleName(), Option.SET_COUNTDOWN_TEXT.getOption(), String.valueOf(countdown));
}
@Override
protected Class<?> setCls() {
return getClass();
}
}
}

View File

@ -0,0 +1,44 @@
package com.unibuy.smartdevice.ui.dialog;
import android.content.Context;
import com.unibuy.smartdevice.DialogAbstract;
import com.unibuy.smartdevice.databinding.DialogSystemInspectionBinding;
import com.unibuy.smartdevice.tools.HandlerMain;
import com.unibuy.smartdevice.tools.ToastHandlerMain;
public class SystemInspectionDialog extends DialogAbstract {
public SystemInspectionDialog(Context context, HandlerMain srcHandlerMain) {
super(context, srcHandlerMain);
getLogs().info("SystemInspectionDialog:" + getClass().getSimpleName());
}
@Override
protected Context setCtx() {
return this.getContext();
}
@Override
protected Class<? extends DialogAbstract> setCls() {
return getClass();
}
@Override
protected HandlerMain setHandlerMain() {
return new ToastHandlerMain(getContext(), getLogs()) {
@Override
protected void execute(Context context, int commandCode, String message) {
super.execute(context, commandCode, message);
}
};
}
private DialogSystemInspectionBinding binding;
@Override
protected void onCreate(Context context) {
binding = DialogSystemInspectionBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:strokeColor="#FF000000"
android:strokeWidth="3"
android:strokeLineCap="round"
android:pathData="M12,5v14M5,12h14"/>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- 使用專案主色 -->
<solid android:color="@color/primary" />
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 頁面背景色 -->
<solid android:color="@color/background" />
<!-- 黑色外框線 -->
<stroke
android:width="1.5dp"
android:color="@color/black" />
<!-- 圓角 -->
<corners android:radius="8dp" />
</shape>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 頁面背景色 -->
<solid android:color="@color/background" />
<!-- 警告色外框線 -->
<stroke
android:width="1.5dp"
android:color="@color/warning" />
<!-- 圓角 -->
<corners android:radius="8dp" />
</shape>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:strokeColor="#FF000000"
android:strokeWidth="3"
android:strokeLineCap="round"
android:pathData="M19,5L5,19M5,5l14,14"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:strokeColor="@color/warning"
android:strokeWidth="3"
android:strokeLineCap="round"
android:pathData="M19,5L5,19M5,5l14,14"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/white">
<path
android:fillColor="@android:color/white"
android:pathData="M20,2H4C3,2 2,2.9 2,4v3.01C2,7.73 2.43,8.35 3,8.7V20c0,1.1 1.1,2 2,2h14c0.9,0 2,-0.9 2,-2V8.7c0.57,-0.35 1,-0.97 1,-1.69V4C22,2.9 21,2 20,2zM15,14H9v-2h6V14zM20,7H4V4h16V7z"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:strokeColor="#FF000000"
android:strokeWidth="3"
android:strokeLineCap="round"
android:pathData="M5,12h14"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@android:color/white">
<path
android:fillColor="@android:color/white"
android:pathData="M6,2 L3,2 L3,4 L5,4 L8.6,11.6 L7.3,14 C7.1,14.3 7,14.7 7,15 C7,16.1 7.9,17 9,17 L21,17 L21,15 L9.4,15 C9.3,15 9.2,14.9 9.2,14.8 L9.2,14.7 L10.1,13 L18,13 C18.8,13 19.5,12.6 19.8,11.9 L23,6.3 L23,6 C23,5.4 22.6,5 22,5 L7.4,5 L6.5,3 Z" />
<path
android:fillColor="@android:color/white"
android:pathData="M9,18 C7.9,18 7,18.9 7,20 C7,21.1 7.9,22 9,22 C10.1,22 11,21.1 11,20 C11,18.9 10.1,18 9,18 Z" />
<path
android:fillColor="@android:color/white"
android:pathData="M19,18 C17.9,18 17,18.9 17,20 C17,21.1 17.9,22 19,22 C20.1,22 21,21.1 21,20 C21,18.9 20.1,18 19,18 Z" />
</vector>

View File

@ -231,37 +231,132 @@
</LinearLayout>
<TextView
<LinearLayout
android:id="@+id/floatButtonPickupCode"
android:layout_width="50dp"
android:layout_height="150dp"
android:text="取\n貨\n碼"
android:textSize="28sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginEnd="24dp"
android:layout_marginBottom="80dp"
android:backgroundTint="@color/gray"
android:textColor="@color/black"
android:alpha="0.8"
android:layout_marginBottom="24dp"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintBottom_toTopOf="@+id/floatButtonShoppingCart"
app:layout_constraintEnd_toEndOf="@+id/bottom_navigation"
android:textStyle="bold"/>
app:layout_constraintEnd_toEndOf="@+id/bottom_navigation">
<com.google.android.material.floatingactionbutton.FloatingActionButton
<androidx.cardview.widget.CardView
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_margin="12dp"
app:cardCornerRadius="16dp"
app:cardBackgroundColor="@color/cardSurface"
app:cardElevation="6dp"
android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:paddingHorizontal="8dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/package_24"
app:tint="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="取貨碼"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<LinearLayout
android:id="@+id/floatButtonShoppingCart"
android:layout_width="58dp"
android:layout_height="51dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_marginEnd="24dp"
android:layout_marginBottom="80dp"
android:contentDescription="TODO"
android:layout_marginBottom="24dp"
android:visibility="gone"
app:backgroundTint="@color/gray"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="@+id/fragment_container"
app:layout_constraintEnd_toEndOf="@+id/bottom_navigation"
app:maxImageSize="60dp"
app:srcCompat="@drawable/baseline_add_shopping_cart_24" />
app:layout_constraintEnd_toEndOf="@+id/bottom_navigation">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false">
<androidx.cardview.widget.CardView
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_margin="12dp"
app:cardCornerRadius="16dp"
app:cardBackgroundColor="@color/cardSurface"
app:cardElevation="6dp"
android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:paddingTop="12dp"
android:paddingBottom="8dp"
android:paddingHorizontal="8dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/shopping_cart_24"
app:tint="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/shopping_cart_title"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/textCartBadge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="34dp"
android:minHeight="34dp"
android:paddingHorizontal="6dp"
android:layout_gravity="top|end"
android:background="@drawable/rounded_background_red"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:elevation="10dp"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
<Button

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="800dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_dialog_rounded"
android:padding="36dp">
<!-- ==========================================
上半部: 標題與副標
========================================== -->
<LinearLayout
android:id="@+id/layoutHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="24dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/product_delivery_success"
android:textSize="44sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/please_go_to_cabinet_to_pick_up_goods"
android:textSize="32sp"
android:textColor="@color/primary"
android:textStyle="bold" />
</LinearLayout>
<!-- ==========================================
中間部: 圓形貨道數字
========================================== -->
<TextView
android:id="@+id/tvLaneNumber"
android:layout_width="260dp"
android:layout_height="260dp"
android:background="@drawable/bg_circle_primary"
android:gravity="center"
android:text="99"
android:textColor="@color/white"
android:textSize="110sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/layoutHeader"
app:layout_constraintBottom_toTopOf="@id/btnConfirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- ==========================================
下半部: 按鈕與商標區域
========================================== -->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@drawable/bg_button_primary"
android:text="@string/confirm_goods_taken_hardcoded"
android:textSize="26sp"
android:textColor="@color/onPrimary"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@id/tvBrand"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvBrand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Powered by Star Helper | 由 Star Helper 提供技術支援"
android:textSize="14sp"
android:textColor="@color/outline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="800dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_dialog_rounded"
android:padding="36dp">
<!-- ==========================================
上半部: 標題
========================================== -->
<LinearLayout
android:id="@+id/layoutHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="36dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/system_inspection_in_progress"
android:textSize="44sp"
android:textStyle="bold"
android:textColor="@color/black"
android:gravity="center"
android:textAlignment="center" />
</LinearLayout>
<!-- ==========================================
中間部: 中間圖示
========================================== -->
<ImageView
android:id="@+id/imgIcon"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/system_settings"
android:scaleType="fitCenter"
app:layout_constraintTop_toBottomOf="@id/layoutHeader"
app:layout_constraintBottom_toTopOf="@id/btnConfirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- ==========================================
下半部: 按鈕與商標區域(按鈕設為 invisible 保留空間結構)
========================================== -->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnConfirm"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="@drawable/bg_button_primary"
android:visibility="invisible"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@id/tvBrand"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/tvBrand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Powered by Star Helper | 由 Star Helper 提供技術支援"
android:textSize="14sp"
android:textColor="@color/outline"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View File

@ -7,12 +7,23 @@
android:background="@color/white"
android:orientation="vertical">
<!-- 購物車上方商品數量 -->
<TextView
android:id="@+id/totalItemsTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="24dp"
android:paddingVertical="16dp"
android:text="@string/total_items_format"
android:textColor="@color/black"
android:textSize="23sp"
android:textStyle="bold" />
<!-- 购物车商品列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/shoppingCartRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginHorizontal="48dp"
android:layout_weight="1"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
@ -30,41 +41,27 @@
android:id="@+id/summaryContainer"
android:layout_width="match_parent"
android:layout_height="120dp"
android:gravity="center|end"
android:orientation="horizontal"
android:paddingHorizontal="40dp">
android:paddingHorizontal="100dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:paddingHorizontal="60dp"
android:paddingVertical="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="小記"
android:textColor="@color/black"
android:textSize="26sp"
android:textStyle="bold" />
<TextView
android:id="@+id/totalItemsTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="40dp"
android:layout_weight="1"
android:gravity="center|end"
android:text="@string/total_items_format"
android:textColor="#767676"
android:textSize="46sp"
android:textStyle="bold" />
<TextView
android:id="@+id/totalAmountTextView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|end"
android:text="@string/total_amount_format"
android:textColor="@color/red"
android:textSize="52sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/totalAmountTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/total_amount_format"
android:textColor="@color/primary"
android:textSize="52sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout

View File

@ -17,11 +17,11 @@
<!-- 1. 圖片 -->
<ImageView
android:id="@+id/image_product"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="centerInside" />
<!-- 2. 標題與單價 -->
<!-- 2. 標題與單價(小記) -->
<LinearLayout
android:id="@+id/layout_product"
android:layout_width="0dp"
@ -37,15 +37,29 @@
android:ellipsize="end"
android:maxLines="2"
android:text="商品"
style="@style/TextAppearance.App.QuickCart.Medium" />
style="@style/TextAppearance.App.QuickCart.Medium"
android:textSize="24sp"
android:textStyle="normal" />
<!-- 單一品項金額,為免 Adapter 找不到 View 而出錯,予以保留但隱藏 -->
<TextView
android:id="@+id/textPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="$ 0"
style="@style/TextAppearance.App.QuickCart.Small"
style="@style/TextAppearance.App.QuickCart.Small" />
<!-- 小記金額(移至此處) -->
<TextView
android:id="@+id/totalPriceTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="$ 0.0000"
style="@style/TextAppearance.App.QuickCart.Medium"
android:textColor="@color/primary" />
</LinearLayout>
@ -59,9 +73,11 @@
<ImageView
android:id="@+id/buttonMinus"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_minus" />
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:background="@drawable/bg_quantity_outline_button"
android:src="@drawable/remove_24" />
<TextView
android:id="@+id/textQuantity"
@ -70,33 +86,26 @@
android:gravity="center"
android:text="1"
style="@style/TextAppearance.App.QuickCart.Medium"
android:textColor="@color/primary" />
android:textColor="@color/black" />
<ImageView
android:id="@+id/buttonPlus"
android:layout_width="56dp"
android:layout_height="56dp"
android:src="@drawable/ic_plus" />
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:background="@drawable/bg_quantity_outline_button"
android:src="@drawable/add_24" />
</LinearLayout>
<!-- 4. 刪除鈕(現有 Adapter / ShoppingCartFragment 沿用) -->
<ImageView
android:id="@+id/buttonWaste"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="12dp"
android:src="@drawable/ic_waste" />
<!-- 5. 小計(現有 Adapter 寫入 totalPriceTextView -->
<TextView
android:id="@+id/totalPriceTextView"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:text="$ 0.0000"
style="@style/TextAppearance.App.QuickCart.Medium" />
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginStart="32dp"
android:padding="10dp"
android:background="@drawable/bg_waste_outline_button"
android:src="@drawable/close_warning_24" />
</LinearLayout>

View File

@ -408,8 +408,8 @@
<string name="add_more_items">Add More Items</string>
<string name="go_to_pay">Proceed to Checkout</string>
<string name="cancel_button_format">Cancel (%d sec)</string>
<string name="total_items_format">Items: (%d)</string>
<string name="total_amount_format">NT$ %d</string>
<string name="total_items_format">Cart Items (%d)</string>
<string name="total_amount_format">NT$%d</string>
<string name="cart_out_of_stock">Out of Stock</string>
<string name="cart_cannot_decrease">Cannot Decrease Further</string>
<string name="cart_max_items">Up to 8 items per cart</string>

View File

@ -410,8 +410,8 @@
<string name="add_more_items">商品を追加</string>
<string name="go_to_pay">お会計へ進む</string>
<string name="cancel_button_format">キャンセル(%d秒</string>
<string name="total_items_format">商品数(%d)</string>
<string name="total_amount_format">NT$ %d</string>
<string name="total_items_format">商品数%d個</string>
<string name="total_amount_format">NT$%d</string>
<string name="cart_out_of_stock">在庫切れ</string>
<string name="cart_cannot_decrease">これ以上減らせません</string>
<string name="cart_max_items">カートは最大8点まで購入できます</string>

View File

@ -327,11 +327,15 @@
<string name="add_more_items">加購商品</string>
<string name="go_to_pay">前往結帳</string>
<string name="cancel_button_format">取消(%d秒</string>
<string name="total_items_format">商品數量:(%d)</string>
<string name="total_amount_format">NT$ %d</string>
<string name="total_items_format">購物車品項(%d件</string>
<string name="total_amount_format">NT$%d</string>
<string name="cart_out_of_stock">超出庫存</string>
<string name="cart_cannot_decrease">不能減少了</string>
<string name="cart_max_items">購物車最多可購買 8 件商品</string>
<string name="cart_added">已加入購物車</string>
<string name="data_error">數據異常</string>
<string name="product_delivery_success">商品出貨成功</string>
<string name="please_go_to_cabinet_to_pick_up_goods">請至99號櫃門拿取您的商品</string>
<string name="confirm_goods_taken_hardcoded">確認已取貨15秒</string>
<string name="system_inspection_in_progress">機器巡檢中請稍後</string>
</resources>