From bd23c31ba157e5503318b82bdd6fe0712f020e4c Mon Sep 17 00:00:00 2001 From: sky121113 Date: Mon, 15 Jun 2026 10:16:29 +0800 Subject: [PATCH] =?UTF-8?q?[FEAT]=20=E5=95=86=E5=93=81=E8=A9=B3=E6=83=85?= =?UTF-8?q?=E9=A0=81=E6=8E=A5=E7=B7=9A=EF=BC=9A=E9=BB=9E=E5=95=86=E5=93=81?= =?UTF-8?q?=E9=96=8B=E8=A9=B3=E6=83=85=E3=80=81=E4=BE=9D=E8=B3=BC=E7=89=A9?= =?UTF-8?q?=E8=BB=8A=E9=96=8B=E9=97=9C=E5=91=88=E7=8F=BE=E6=8C=89=E9=88=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增 DialogProductDetail:把原本只有佈局的商品詳情頁接活,顯示商品圖、多語名稱、貨道、庫存、數量與金額小計。 2. 依雲端 DevSet.ShoppingCar 呈現按鈕:購物車開啟顯示「數量調整+加入購物車+直接購買」;購物車關閉(一般版)隱藏「數量調整+加入購物車」,只留「直接購買」且數量固定 1。 3. 加入購物車以選定數量逐件加入(沿用 CartViewModel 庫存/8 件上限防呆);直接購買清空 buyList 放入本商品後走既有 BuyDialog 選付款。 4. BasicSaleFlow.handleProductSelected 改為點商品一律先彈出詳情頁。 5. RecyclerVmcBuyListAdpter 商品卡右下角「+」(buttonQuickAdd) 接線:僅購物車開啟時顯示並快速加購一件,關閉時隱藏。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../unibuy/smartdevice/ui/BasicSaleFlow.java | 14 +- .../ui/devs/vmc/RecyclerVmcBuyListAdpter.java | 14 ++ .../ui/dialog/DialogProductDetail.java | 145 ++++++++++++++++++ 3 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/com/unibuy/smartdevice/ui/dialog/DialogProductDetail.java diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/BasicSaleFlow.java b/app/src/main/java/com/unibuy/smartdevice/ui/BasicSaleFlow.java index 5f82373..5c2f377 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/BasicSaleFlow.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/BasicSaleFlow.java @@ -39,17 +39,9 @@ public class BasicSaleFlow extends SaleFlowHandler { */ @Override public boolean handleProductSelected(SlotStructure slot) { - if (MyApp.getInstance().getDevSet().isShoppingCar()) { - UnibuyHelper.INSTANCE.getCartViewModel().addToCart(slot); - ToastUtils.showShort(R.string.cart_added); - } else { - // 單品直購:每次點擊都是一筆全新交易,清空 buyList 後僅放入本商品, - // 交由 BuyDialog 的「單品模式」分支(依貨道屬性篩付款/發票,讀 getBuyList().get(0))。 - MyApp.getInstance().getBuyList().clear(); - MyApp.getInstance().getBuyList().add( - new BuyStructure(slot.getField(), slot.getSlot(), slot.getProduct(), 1)); - onBuyRequested(); - } + // 點商品一律先彈出商品詳情頁;詳情頁內依購物車開關呈現 + // 「數量調整+加入購物車+直接購買」或僅「直接購買」,再走後續加購/單品直購流程。 + new com.unibuy.smartdevice.ui.dialog.DialogProductDetail(context, handlerMain, slot).show(); return true; } diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java index 52f9823..0276229 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/devs/vmc/RecyclerVmcBuyListAdpter.java @@ -118,6 +118,20 @@ public class RecyclerVmcBuyListAdpter extends RecyclerView.Adapter 0 && !isLock) { + holder.binding.buttonQuickAdd.setVisibility(View.VISIBLE); + holder.binding.buttonQuickAdd.setOnClickListener(v -> { + if (MyApp.getInstance().isMachineBusy()) return; + com.unibuy.v2.UnibuyHelper.INSTANCE.getCartViewModel().addToCart(slot); + com.blankj.utilcode.util.ToastUtils.showShort(R.string.cart_added); + }); + } else { + holder.binding.buttonQuickAdd.setVisibility(View.GONE); + holder.binding.buttonQuickAdd.setOnClickListener(null); + } + // devRunVMC(0); } diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DialogProductDetail.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DialogProductDetail.java new file mode 100644 index 0000000..884a5c7 --- /dev/null +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DialogProductDetail.java @@ -0,0 +1,145 @@ +package com.unibuy.smartdevice.ui.dialog; + +import android.content.Context; + +import com.blankj.utilcode.util.ToastUtils; +import com.unibuy.smartdevice.DialogAbstract; +import com.unibuy.smartdevice.MyApp; +import com.unibuy.smartdevice.R; +import com.unibuy.smartdevice.databinding.DialogProductDetailBinding; +import com.unibuy.smartdevice.exception.LogsEmptyException; +import com.unibuy.smartdevice.structure.BuyStructure; +import com.unibuy.smartdevice.structure.SlotStructure; +import com.unibuy.smartdevice.tools.HandlerMain; +import com.unibuy.smartdevice.tools.ToastHandlerMain; +import com.unibuy.smartdevice.ui.FontendActivity; +import com.unibuy.smartdevice.ui.SaleFlowHandler; +import com.unibuy.smartdevice.ui.tools.ImageGlide; +import com.unibuy.v2.UnibuyHelper; + +/** + * 商品詳情對話框。 + * 點選商品後一律先彈出此頁,依雲端 B014 DevSet.ShoppingCar 決定按鈕: + * - 購物車開啟:顯示「數量調整 + 加入購物車 + 直接購買」。 + * - 購物車關閉(一般版):隱藏「數量調整 + 加入購物車」,只留「直接購買」(數量固定 1)。 + * 「直接購買」沿用既有單品直購流程(清空 buyList → BuyDialog 選付款)。 + */ +public class DialogProductDetail extends DialogAbstract { + + private DialogProductDetailBinding binding; + private final SlotStructure slot; + private int quantity = 1; + + public DialogProductDetail(Context context, HandlerMain srcHandlerMain, SlotStructure slot) { + super(context, srcHandlerMain); + this.slot = slot; + } + + @Override + protected Context setCtx() { + return getContext(); + } + + @Override + protected Class setCls() { + return getClass(); + } + + @Override + protected HandlerMain setHandlerMain() { + return new ToastHandlerMain(getContext(), getLogs()) { + @Override + protected void execute(Context context, int commandCode, String message) { + // 本對話框不需處理回呼指令 + } + }; + } + + @Override + protected void onCreate(Context context) { + binding = DialogProductDetailBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + // 商品圖片 + try { + new ImageGlide(context).fileload(slot.getProduct().getProductImg(), binding.imageProduct); + } catch (LogsEmptyException e) { + getLogs().warning(e); + } + + // 商品名稱(多語)、貨道、庫存 + binding.textProductName.setText(slot.getProduct().getLocalizedName(context)); + binding.slotNumber.setText("貨道" + slot.getSlot()); + binding.inventoryNumber.setText("庫存" + slot.getCount()); + + // 依購物車開關決定按鈕呈現 + boolean cartOn = MyApp.getInstance().getDevSet().isShoppingCar(); + if (!cartOn) { + // 一般版:隱藏數量調整與加入購物車,只留直接購買,數量固定 1 + binding.layoutQuantityControl.setVisibility(android.view.View.GONE); + binding.btnAddToCart.setVisibility(android.view.View.GONE); + quantity = 1; + } + + refreshQuantity(); + + binding.ivCancel.setOnClickListener(v -> cancel()); + + binding.buttonMinus.setOnClickListener(v -> { + if (quantity > 1) { + quantity--; + refreshQuantity(); + } + }); + + binding.buttonPlus.setOnClickListener(v -> { + // 上限:貨道庫存與購物車總量上限(8 件) + if (quantity >= slot.getCount()) { + ToastUtils.showShort(R.string.cart_out_of_stock); + return; + } + if (quantity >= 8) { + ToastUtils.showShort(R.string.cart_max_items); + return; + } + quantity++; + refreshQuantity(); + }); + + // 加入購物車:以選定數量逐件加入(CartViewModel 內建庫存/8 件上限防呆與提示) + binding.btnAddToCart.setOnClickListener(v -> { + for (int i = 0; i < quantity; i++) { + UnibuyHelper.INSTANCE.getCartViewModel().addToCart(slot); + } + ToastUtils.showShort(R.string.cart_added); + cancel(); + }); + + // 直接購買:清空 buyList,僅放入本商品(含數量),交既有單品直購流程彈 BuyDialog 選付款 + binding.btnBuyNow.setOnClickListener(v -> { + MyApp.getInstance().getBuyList().clear(); + MyApp.getInstance().getBuyList().add( + new BuyStructure(slot.getField(), slot.getSlot(), slot.getProduct(), quantity)); + cancel(); + requestBuy(context); + }); + } + + private void refreshQuantity() { + binding.textQuantity.setText(String.valueOf(quantity)); + int total = slot.getProduct().getRealPrice() * quantity; + binding.textPrice.setText("$" + total); + } + + /** 沿用各 flavor 的結帳入口(basic→BuyDialog);非 FontendActivity 時直接開 BuyDialog。 */ + private void requestBuy(Context context) { + if (context instanceof FontendActivity) { + SaleFlowHandler handler = ((FontendActivity) context).getSaleFlowHandler(); + if (handler != null) { + handler.onBuyRequested(); + return; + } + } + new BuyDialog(context, getSrcHandlerMain()).show(); + } +}