[FEAT] 商品詳情頁接線:點商品開詳情、依購物車開關呈現按鈕

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) <noreply@anthropic.com>
This commit is contained in:
sky121113 2026-06-15 10:16:29 +08:00
parent 0900dc20f9
commit bd23c31ba1
3 changed files with 162 additions and 11 deletions

View File

@ -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;
}

View File

@ -118,6 +118,20 @@ public class RecyclerVmcBuyListAdpter extends RecyclerView.Adapter<RecyclerVmcBu
holder.binding.imageProductPicture.setOnClickListener(null);
}
// 商品卡右下角+快速加購僅購物車功能開啟時顯示無購物車時隱藏只能點商品開詳情頁
boolean cartOn = MyApp.getInstance().getDevSet().isShoppingCar();
if (cartOn && count > 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);
}

View File

@ -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<? extends DialogAbstract> 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();
}
}