This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-samples.git


The following commit(s) were added to refs/heads/master by this push:
     new 9768781d6 Improve the functionality of the shop project (#1180)
9768781d6 is described below

commit 9768781d6dd8d3d5cbf2ffef67f15e71b367ca0d
Author: heliang666s <[email protected]>
AuthorDate: Fri Aug 30 20:42:12 2024 +0800

    Improve the functionality of the shop project (#1180)
---
 .../dubbo/shop/service/cart/CartServiceImpl.java   | 14 ++--
 .../dubbo/shop/checkout/CheckoutServiceImpl.java   | 59 +++++++--------
 .../apache/dubbo/shop/common/utils/MoneyUtils.java | 19 +++--
 .../dubbo/shop/frontend/FrontendApplication.java   |  4 +-
 .../dubbo/shop/frontend/FrontendController.java    | 85 +++++++++++++++-------
 .../src/main/resources/templates/cart.html         | 32 ++++----
 .../src/main/resources/templates/error.html        |  4 +-
 .../src/main/resources/templates/home.html         |  8 +-
 .../src/main/resources/templates/order.html        | 12 +--
 .../src/main/resources/templates/product.html      | 63 +++++++++-------
 .../main/resources/templates/recommendations.html  |  4 +-
 .../productcatalogs/ProductCatalogServiceImpl.java | 13 ++--
 12 files changed, 182 insertions(+), 135 deletions(-)

diff --git 
a/online_bontique_demo/cartService/src/main/java/org/apache/dubbo/shop/service/cart/CartServiceImpl.java
 
b/online_bontique_demo/cartService/src/main/java/org/apache/dubbo/shop/service/cart/CartServiceImpl.java
index bf9ef552a..f2ac7142a 100644
--- 
a/online_bontique_demo/cartService/src/main/java/org/apache/dubbo/shop/service/cart/CartServiceImpl.java
+++ 
b/online_bontique_demo/cartService/src/main/java/org/apache/dubbo/shop/service/cart/CartServiceImpl.java
@@ -32,16 +32,16 @@ import java.util.Map;
 @DubboService
 @Service
 public class CartServiceImpl implements CartService {
-    
+
     private final Map<String, List<CartItem>> cartStore = new HashMap<>();
     @Override
     public void addItem(String userId, CartItem newItem) {
         // Retrieve the list of cart items for the user, create a new list if 
it doesn't exist
         List<CartItem> cartItems = cartStore.computeIfAbsent(userId, k -> new 
ArrayList<>());
-        
+
         // Flag to check if the item was updated
         boolean itemUpdated = false;
-        
+
         // Iterate through the list to check if the item already exists
         for (CartItem item : cartItems) {
             if (item.getProductId().equals(newItem.getProductId())) {
@@ -51,22 +51,22 @@ public class CartServiceImpl implements CartService {
                 break;
             }
         }
-        
+
         // If the item was not updated, add it as a new item
         if (!itemUpdated) {
             cartItems.add(newItem);
         }
-        
+
         // Update the cartStore with the new list
         cartStore.put(userId, cartItems);
     }
-    
+
     @Override
     public Cart getCart(String userId) {
         List<CartItem> items = cartStore.getOrDefault(userId, new 
ArrayList<>());
         return new Cart(userId, items);
     }
-    
+
     @Override
     public void emptyCart(String userId) {
         cartStore.remove(userId);
diff --git 
a/online_bontique_demo/checkoutService/src/main/java/org/apache/dubbo/shop/checkout/CheckoutServiceImpl.java
 
b/online_bontique_demo/checkoutService/src/main/java/org/apache/dubbo/shop/checkout/CheckoutServiceImpl.java
index fbcd64d08..66f1f1457 100644
--- 
a/online_bontique_demo/checkoutService/src/main/java/org/apache/dubbo/shop/checkout/CheckoutServiceImpl.java
+++ 
b/online_bontique_demo/checkoutService/src/main/java/org/apache/dubbo/shop/checkout/CheckoutServiceImpl.java
@@ -60,7 +60,7 @@ import java.util.UUID;
 @Service
 @Slf4j
 public class CheckoutServiceImpl implements CheckoutService {
-    
+
     @DubboReference
     private CartService cartService;
     @DubboReference
@@ -73,40 +73,40 @@ public class CheckoutServiceImpl implements CheckoutService 
{
     private ProductCatalogService productCatalogService;
     @DubboReference
     private ShippingService shippingService;
-    
+
     @Override
     public PlaceOrderResponse placeOrder(PlaceOrderRequest request) {
         log.info("[PlaceOrder] user_id={} user_currency={}", 
request.getUserId(), request.getUserCurrency());
         String orderId = UUID.randomUUID().toString();
-        
+
         OrderPrep prep = 
prepareOrderItemsAndShippingQuoteFromCart(request.getUserId(), 
request.getUserCurrency(), request.getAddress());
-        
+
         Money total = new Money(request.getUserCurrency(), 0L, 0);
         total = MoneyUtils.sum(total, prep.getShippingCostLocalized());
         for (OrderItem item : prep.getOrderItems()) {
             Money multPrice = MoneyUtils.multiplySlow(item.getCost(), 
item.getItem().getQuantity());
             total = MoneyUtils.sum(total, multPrice);
         }
-        
+
         String txId = changeCard(total, request.getCreditCard());
         log.info("payment went through (transaction_id: {})", txId);
-        
+
         String shipmentTrackingId = shipOrder(request.getAddress(), 
prep.getCartItems());
-        
+
         emptyUserCart(request.getUserId());
-        
+
         OrderResult orderResult = new OrderResult();
         orderResult.setOrderId(orderId);
         orderResult.setShippingTrackingId(shipmentTrackingId);
         orderResult.setShippingCost(prep.getShippingCostLocalized());
         orderResult.setShippingAddress(request.getAddress());
         orderResult.setItems(prep.getOrderItems());
-        
+
         sendOrderConfirmation(request.getEmail(), orderResult);
-        
+
         return new PlaceOrderResponse(orderResult);
     }
-    
+
     @Override
     public OrderPrep prepareOrderItemsAndShippingQuoteFromCart(String userId, 
String userCurrency, Address address) {
         OrderPrep out = new OrderPrep();
@@ -114,89 +114,86 @@ public class CheckoutServiceImpl implements 
CheckoutService {
         List<OrderItem> orderItems = prepOrderItems(cartItems, userCurrency);
         Money shippingUSD = quoteShipping(address, cartItems);
         Money shippingPrice = covertCurrency(shippingUSD, userCurrency);
-        
+
         out.setShippingCostLocalized(shippingPrice);
         out.setOrderItems(orderItems);
         out.setCartItems(cartItems);
-        
+
         return out;
     }
-    
+
     @Override
     public Money quoteShipping(Address address, List<CartItem> items) {
         GetQuoteRequest request = new GetQuoteRequest();
         request.setAddress(address);
         request.setItems(items);
-        
+
         GetQuoteResponse response = shippingService.getQuote(request);
         return response.getCostUsd();
     }
-    
+
     @Override
     public List<CartItem> getUserCart(String userId) {
-        GetCartRequest request = new GetCartRequest();
-        request.setUserId(userId);
-        
         Cart cart = cartService.getCart(userId);
         return cart.getItems();
     }
-    
+
     @Override
     public void emptyUserCart(String userId) {
         EmptyCartRequest request = new EmptyCartRequest();
         request.setUserId(userId);
         cartService.emptyCart(userId);
     }
-    
+
     @Override
     public List<OrderItem> prepOrderItems(List<CartItem> items, String 
userCurrency) {
         List<OrderItem> out = new ArrayList<>();
         for (CartItem item : items) {
             GetProductRequest request = new GetProductRequest();
             request.setId(item.getProductId());
-            
+
             Product product = productCatalogService.getProduct(request);
             Money price = covertCurrency(product.getPriceUsd(), userCurrency);
-            
+
             OrderItem orderItem = new OrderItem();
             orderItem.setCost(price);
             orderItem.setItem(item);
-            
+
             out.add(orderItem);
         }
         return out;
     }
-    
+
     @Override
     public Money covertCurrency(Money from, String toCurrency) {
         CurrencyConversionRequest request = new CurrencyConversionRequest();
         request.setFrom(from);
         request.setToCode(toCurrency);
-        
+
         return currencyService.convert(request);
     }
-    
+
     @Override
     public String changeCard(Money amount, CreditCardInfo paymentInfo) {
         ChargeRequest request = new ChargeRequest();
         request.setAmount(amount);
         request.setCreditCard(paymentInfo);
-        
+
         ChargeResponse response = paymentService.charge(request);
         return response.getTransactionId();
     }
-    
+
     @Override
     public void sendOrderConfirmation(String email, OrderResult order) {
         emailService.sendOrderConfirmation(email, order.getOrderId());
     }
-    
+
     @Override
     public String shipOrder(Address address, List<CartItem> items) {
         ShipOrderRequest request = new ShipOrderRequest();
         request.setAddress(address);
         request.setItems(items);
-        
+
         ShipOrderResponse response = shippingService.shipOrder(request);
         return response.getTrackingId();
     }
diff --git 
a/online_bontique_demo/common/src/main/java/org/apache/dubbo/shop/common/utils/MoneyUtils.java
 
b/online_bontique_demo/common/src/main/java/org/apache/dubbo/shop/common/utils/MoneyUtils.java
index 19ddc9185..62051f2e6 100644
--- 
a/online_bontique_demo/common/src/main/java/org/apache/dubbo/shop/common/utils/MoneyUtils.java
+++ 
b/online_bontique_demo/common/src/main/java/org/apache/dubbo/shop/common/utils/MoneyUtils.java
@@ -20,17 +20,17 @@ package org.apache.dubbo.shop.common.utils;
 import org.apache.dubbo.shop.common.pojo.Money;
 
 public class MoneyUtils {
-    
+
     public static Money sum(Money a, Money b) {
         if (!isValid(a) || !isValid(b)) {
             throw new IllegalArgumentException("Invalid money value");
         } else if (!a.getCurrencyCode().equals(b.getCurrencyCode())) {
             throw new IllegalArgumentException("Mismatching currency codes");
         }
-        
+
         long units = a.getUnits() + b.getUnits();
         int nanos = a.getNanos() + b.getNanos();
-        
+
         if ((units >= 0 && nanos >= 0) || (units < 0 && nanos <= 0)) {
             units += nanos / 1_000_000_000;
             nanos %= 1_000_000_000;
@@ -45,7 +45,12 @@ public class MoneyUtils {
         }
         return new Money(a.getCurrencyCode(), units, nanos);
     }
-    
+
+    public static Money reset(Money money){
+        money.setNanos(0);
+        money.setUnits(0L);
+        return money;
+    }
     public static Money multiplySlow(Money money, int multiplier) {
         Money result = money;
         for (int i = 1; i < multiplier; i++) {
@@ -53,15 +58,15 @@ public class MoneyUtils {
         }
         return result;
     }
-    
+
     public static Boolean isValid(Money money) {
         return signMatches(money) && validNanos(money.getNanos());
     }
-    
+
     private static Boolean signMatches(Money money) {
         return money.getNanos() == 0 || money.getUnits() == 0 || 
(money.getNanos() < 0) == (money.getUnits() < 0);
     }
-    
+
     private static Boolean validNanos(Integer nanos) {
         return -999_999_999 <= nanos && nanos <= 999_999_999;
     }
diff --git 
a/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendApplication.java
 
b/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendApplication.java
index 876813e76..a3c730550 100644
--- 
a/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendApplication.java
+++ 
b/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendApplication.java
@@ -25,10 +25,10 @@ import 
org.springframework.boot.autoconfigure.SpringBootApplication;
 @SpringBootApplication
 @EnableDubbo
 public class FrontendApplication {
-    
+
     public static void main(String[] args) {
         SpringApplication.run(FrontendApplication.class, args);
         System.out.println("FrontendApplication is running");
     }
-    
+
 }
diff --git 
a/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendController.java
 
b/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendController.java
index 5ac107a60..7c0d797df 100644
--- 
a/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendController.java
+++ 
b/online_bontique_demo/frontend/src/main/java/org/apache/dubbo/shop/frontend/FrontendController.java
@@ -24,8 +24,10 @@ import 
org.apache.dubbo.shop.common.dto.request.GetProductRequest;
 import org.apache.dubbo.shop.common.dto.request.GetQuoteRequest;
 import org.apache.dubbo.shop.common.dto.request.ListRecommendationsRequest;
 import org.apache.dubbo.shop.common.dto.request.PlaceOrderRequest;
+import org.apache.dubbo.shop.common.dto.response.AdResponse;
 import org.apache.dubbo.shop.common.dto.response.ListProductsResponse;
 import org.apache.dubbo.shop.common.dto.response.ListRecommendationsResponse;
+import org.apache.dubbo.shop.common.dto.response.PlaceOrderResponse;
 import org.apache.dubbo.shop.common.pojo.Ad;
 import org.apache.dubbo.shop.common.pojo.Address;
 import org.apache.dubbo.shop.common.pojo.Cart;
@@ -37,9 +39,6 @@ import org.apache.dubbo.shop.common.utils.MoneyUtils;
 import org.apache.dubbo.shop.service.AdsService;
 import org.apache.dubbo.shop.service.CartService;
 import org.apache.dubbo.shop.service.CheckoutService;
-import org.apache.dubbo.shop.service.CurrencyService;
-import org.apache.dubbo.shop.service.EmailService;
-import org.apache.dubbo.shop.service.PaymentService;
 import org.apache.dubbo.shop.service.ProductCatalogService;
 import org.apache.dubbo.shop.service.RecommendationService;
 import org.apache.dubbo.shop.service.ShippingService;
@@ -47,6 +46,8 @@ import org.apache.dubbo.shop.service.ShippingService;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 
@@ -68,16 +69,12 @@ public class FrontendController {
     @DubboReference
     private ProductCatalogService productCatalogService;
     @DubboReference
-    private CurrencyService currencyService;
-    @DubboReference
-    private PaymentService paymentService;
-    @DubboReference
-    private EmailService emailService;
-    @DubboReference
     private CheckoutService checkoutService;
     @DubboReference
     private AdsService adsService;
 
+    static Money totalCost = new Money("USD", 0L, 0);
+    static int totalQuantity = 0;
     @PostMapping("/cart/add")
     public String addItemToCart(@RequestParam String productId, @RequestParam 
Integer quantity, @RequestParam String userId) {
         CartItem item = new CartItem(productId, quantity);
@@ -95,9 +92,12 @@ public class FrontendController {
         List<CartItem> items = cart.getItems();
 
         Map<Product, Integer> productQuantityMap = new HashMap<>();
-        int totalQuantity = 0;
+
 
         List<String> productIds = new ArrayList<>();
+        totalQuantity = 0;
+       MoneyUtils.reset(totalCost);
+
         for (CartItem item : items) {
             totalQuantity += item.getQuantity();
             Product product = productCatalogService.getProduct(new 
GetProductRequest(item.getProductId()));
@@ -107,7 +107,6 @@ public class FrontendController {
             }
         }
 
-        Money totalCost = new Money("USD", 0L, 0);
         for (Map.Entry<Product, Integer> entry : 
productQuantityMap.entrySet()) {
             totalCost = MoneyUtils.sum(totalCost, 
MoneyUtils.multiplySlow(entry.getKey().getPriceUsd(), entry.getValue()));
         }
@@ -123,34 +122,69 @@ public class FrontendController {
         model.addAttribute("total_cost", totalCost);
         model.addAttribute("shipping_cost", shippingService.getQuote(new 
GetQuoteRequest(new Address(), items)));
 
+        model.addAttribute("email", "[email protected]");
+        model.addAttribute("street_address", "1600 Amphitheatre Parkway");
+        model.addAttribute("zip_code", "94043");
+        model.addAttribute("city", "Mountain View");
+        model.addAttribute("state", "CA");
+        model.addAttribute("country", "United States");
+        model.addAttribute("credit_card_number", "4432-8015-6152-0454");
+        model.addAttribute("cvv", "123");
+        // Add any other default values needed
+
         return "cart";
     }
 
     @PostMapping("/cart/empty")
     public String emptyCart(String userId) {
         cartService.emptyCart("1");
+        totalQuantity = 0;
         return "redirect:/cart";
     }
 
     @PostMapping("/cart/checkout")
-    public String checkout(String userId) {
-        cartService.emptyCart("1");
-        return "redirect:/";
-    }
+    public String checkout(@ModelAttribute PlaceOrderRequest 
placeOrderRequest,Model model) throws ExecutionException, InterruptedException {
+        PlaceOrderResponse placeOrderResponse = 
checkoutService.placeOrder(placeOrderRequest);
 
-    @GetMapping("/products")
-    public String listProducts(Model model) {
-        ListProductsResponse response = productCatalogService.listProducts(new 
Empty());
+        checkoutService.emptyUserCart("1");
+        totalQuantity = 0;
+        checkoutService.sendOrderConfirmation(placeOrderRequest.getEmail(), 
placeOrderResponse.getOrder());
+
+        ListRecommendationsResponse recommendations = 
recommendationService.listRecommendations(new ListRecommendationsRequest("1", 
new ArrayList<>()));
+        List<Product> products = new ArrayList<>();
+        for(String productId : recommendations.getProductIds()){
+            products.add(productCatalogService.getProduct(new 
GetProductRequest(productId)));
+        }
+
+        model.addAttribute("order",placeOrderResponse.getOrder());
+        model.addAttribute("total_cost",totalCost);
+        model.addAttribute("recommendations",products);
         model.addAttribute("is_cymbal_brand", false);
         model.addAttribute("show_currency", false);
-        model.addAttribute("products", response.getProducts());
-        return "product";
+        return "order";
     }
-    @GetMapping("/order")
-    public String placeOrder(Model model) {
+
+    @GetMapping("/product/{id}")
+    public String product(@PathVariable String id, Model model) throws 
ExecutionException, InterruptedException {
+        Product product = productCatalogService.getProduct(new 
GetProductRequest(id));
+
         model.addAttribute("is_cymbal_brand", false);
-        model.addAttribute(checkoutService.placeOrder(new 
PlaceOrderRequest()).getOrder());
-        return "order";
+        model.addAttribute("show_currency", false);
+        model.addAttribute("product",product);
+
+        ListRecommendationsResponse recommendations = 
recommendationService.listRecommendations(new ListRecommendationsRequest("1", 
List.of(product.getId())));
+        List<Product> products = new ArrayList<>();
+        for(String productId : recommendations.getProductIds()){
+            products.add(productCatalogService.getProduct(new 
GetProductRequest(productId)));
+        }
+
+        AdRequest adRequest = new AdRequest(List.of(id));
+        AdResponse ads = adsService.getAds(adRequest);
+
+        model.addAttribute("recommendations",products);
+        model.addAttribute("ad", ads.getAds().get(0));
+        model.addAttribute("cart_size",totalQuantity);
+        return "product";
     }
 
     @GetMapping("/ad")
@@ -161,11 +195,12 @@ public class FrontendController {
         return "ad";
     }
 
-    @GetMapping({"/"})
+    @GetMapping({"/static"})
     public String listUser(Model model) {
         model.addAttribute("is_cymbal_brand", false);
         ListProductsResponse response = productCatalogService.listProducts(new 
Empty());
         model.addAttribute("products", response.getProducts());
+        model.addAttribute("cart_size",totalQuantity);
         return "home";
     }
 }
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/cart.html 
b/online_bontique_demo/frontend/src/main/resources/templates/cart.html
index 5c9b41eaf..bcb3cde50 100644
--- a/online_bontique_demo/frontend/src/main/resources/templates/cart.html
+++ b/online_bontique_demo/frontend/src/main/resources/templates/cart.html
@@ -33,14 +33,14 @@
 <!-- 引用 Header -->
 <div th:replace="header :: header"></div>
 
-<div th:class="local">
-    <span class="platform-flag" th:text="local"></span>
+<div th:class="alibaba-platform">
+    <span class="platform-flag" th:text="AlibabaCloud"></span>
 </div>
 
 <main role="main" class="cart-sections">
 
     <!-- 判断购物车是否为空 -->
-    <div th:if="${#lists.isEmpty(items)}">
+    <div th:if="${cart_size <= 0}">
         <section class="empty-cart-section">
             <h3>Your shopping cart is empty!</h3>
             <p>Items you add to your shopping cart will appear here.</p>
@@ -49,7 +49,7 @@
     </div>
 
     <!-- 如果购物车不为空 -->
-    <div th:unless="${#lists.isEmpty(items)}">
+    <div th:unless="${cart_size <= 0}">
         <section class="container">
             <div class="row">
 
@@ -94,7 +94,7 @@
                                 </div>
                                 <div class="col pr-md-0 text-right">
                                     <strong>$</strong>
-                                    <strong 
th:text="${entry.key.priceUsd.units + (entry.key.priceUsd.nanos / 
100000000.0)}"></strong>
+                                    <strong 
th:text="${entry.key.priceUsd.units + (entry.key.priceUsd.nanos / 
1000000000.0)}"></strong>
                                 </div>
                             </div>
                         </div>
@@ -107,13 +107,15 @@
 
                     <div class="row cart-summary-total-row">
                         <div class="col pl-md-0">Total</div>
-                        <div class="col pr-md-0 text-right" th:text="'$ ' 
+${total_cost.units + (total_cost.nanos / 100000000.0)}"></div>
+                        <div class="col pr-md-0 text-right" th:text="'$ ' 
+${total_cost.units + (total_cost.nanos / 1000000000.0)}"></div>
                     </div>
 
                 </div>
 
                 <div class="col-lg-5 offset-lg-1 col-xl-4">
                     <form class="cart-checkout-form" 
th:action="@{/cart/checkout}" method="POST">
+                        <input type="hidden" name="userId" value="1" />
+                        <input type="hidden" name="userCurrency" value="USD" />
 
                         <div class="row">
                             <div class="col">
@@ -131,32 +133,32 @@
                         <div class="form-row">
                             <div class="col cymbal-form-field">
                                 <label for="street_address">Street 
Address</label>
-                                <input type="text" name="street_address" 
id="street_address" th:value="${street_address}" required>
+                                <input type="text" 
name="address.streetAddress" id="street_address" th:value="${street_address}" 
required>
                             </div>
                         </div>
 
                         <div class="form-row">
                             <div class="col cymbal-form-field">
                                 <label for="zip_code">Zip Code</label>
-                                <input type="text" name="zip_code" 
id="zip_code" th:value="${zip_code}" required pattern="\d{4,5}">
+                                <input type="text" name="address.zipCode" 
id="zip_code" th:value="${zip_code}" required pattern="\d{4,5}">
                             </div>
                         </div>
 
                         <div class="form-row">
                             <div class="col cymbal-form-field">
                                 <label for="city">City</label>
-                                <input type="text" name="city" id="city" 
th:value="${city}" required>
+                                <input type="text" name="address.city" 
id="city" th:value="${city}" required>
                             </div>
                         </div>
 
                         <div class="form-row">
                             <div class="col-md-5 cymbal-form-field">
                                 <label for="state">State</label>
-                                <input type="text" name="state" id="state" 
th:value="${state}" required>
+                                <input type="text" name="address.state" 
id="state" th:value="${state}" required>
                             </div>
                             <div class="col-md-7 cymbal-form-field">
                                 <label for="country">Country</label>
-                                <input type="text" id="country" name="country" 
th:value="${country}" placeholder="Country Name" required>
+                                <input type="text" id="country" 
name="address.country" th:value="${country}" placeholder="Country Name" 
required>
                             </div>
                         </div>
 
@@ -169,13 +171,13 @@
                         <div class="form-row">
                             <div class="col cymbal-form-field">
                                 <label for="credit_card_number">Credit Card 
Number</label>
-                                <input type="text" id="credit_card_number" 
name="credit_card_number" th:value="${credit_card_number}" 
placeholder="0000-0000-0000-0000" required pattern="\d{4}-\d{4}-\d{4}-\d{4}">
+                                <input type="text" id="credit_card_number" 
name="creditCard.creditCardNumber" th:value="${credit_card_number}" 
placeholder="0000-0000-0000-0000" required pattern="\d{4}-\d{4}-\d{4}-\d{4}">
                             </div>
                         </div>
                         <div class="form-row">
                             <div class="col-md-5 cymbal-form-field">
                                 <label 
for="credit_card_expiration_month">Month</label>
-                                <select name="credit_card_expiration_month" 
id="credit_card_expiration_month">
+                                <select 
name="creditCard.creditCardExpirationMonth" id="credit_card_expiration_month">
                                     <option value="01">January</option>
                                     <option value="02">February</option>
                                     <option value="03">March</option>
@@ -193,7 +195,7 @@
                             </div>
                             <div class="col-md-4 cymbal-form-field">
                                 <label 
for="credit_card_expiration_year">Year</label>
-                                <select name="credit_card_expiration_year" 
id="credit_card_expiration_year">
+                                <select 
name="creditCard.creditCardExpirationYear" id="credit_card_expiration_year">
                                     <option value="2013">2013</option>
                                     <option value="2014">2014</option>
                                     <option value="2015">2015</option>
@@ -211,7 +213,7 @@
                             </div>
                             <div class="col-md-3 cymbal-form-field">
                                 <label for="credit_card_cvv">CVV</label>
-                                <input type="password" id="credit_card_cvv" 
name="credit_card_cvv" required pattern="\d{3}">
+                                <input type="password" id="credit_card_cvv" 
name="creditCard.creditCardCvv"  required pattern="\d{3}" th:value="${cvv}">
                             </div>
                         </div>
 
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/error.html 
b/online_bontique_demo/frontend/src/main/resources/templates/error.html
index 035f04330..1fe655d22 100644
--- a/online_bontique_demo/frontend/src/main/resources/templates/error.html
+++ b/online_bontique_demo/frontend/src/main/resources/templates/error.html
@@ -27,8 +27,8 @@
 </head>
 <body>
 
-<div th:with="platformCss=${platform_css}" th:class="${platformCss}">
-    <span class="platform-flag" th:text="${platform_name}"></span>
+<div th:class="alibaba-platform">
+    <span class="platform-flag" th:text="AlibabaCloud"></span>
 </div>
 
 <main role="main">
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/home.html 
b/online_bontique_demo/frontend/src/main/resources/templates/home.html
index 6ed5c10cf..e1c64b667 100644
--- a/online_bontique_demo/frontend/src/main/resources/templates/home.html
+++ b/online_bontique_demo/frontend/src/main/resources/templates/home.html
@@ -29,8 +29,8 @@
 <div th:replace="header :: header"></div>
 
 <!-- Platform Section -->
-<div th:class="local">
-  <span class="platform-flag" th:text="local"></span>
+<div th:class="alibaba-platform">
+  <span class="platform-flag" th:text="AlibabaCloud"></span>
 </div>
 
 <main role="main" class="home">
@@ -54,13 +54,13 @@
 
           <!-- Loop through products -->
           <div th:each="product : ${products}" class="col-md-4 
hot-product-card">
-            <a href="/products">
+              <a th:href="@{|/product/${product.id}|}">
               <img alt="" th:src="@{${product.picture}}">
               <div class="hot-product-card-img-overlay"></div>
             </a>
             <div>
               <div class="hot-product-card-name" 
th:text="${product.name}"></div>
-              <div class="hot-product-card-price" th:text="'$ ' + 
${product.priceUsd.units + (product.priceUsd.nanos / 100000000.0)}"></div>
+              <div class="hot-product-card-price" th:text="'$ ' + 
${product.priceUsd.units + (product.priceUsd.nanos / 1000000000.0)}"></div>
             </div>
           </div>
 
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/order.html 
b/online_bontique_demo/frontend/src/main/resources/templates/order.html
index cffcbf7df..203b3cee3 100644
--- a/online_bontique_demo/frontend/src/main/resources/templates/order.html
+++ b/online_bontique_demo/frontend/src/main/resources/templates/order.html
@@ -28,9 +28,8 @@
 <!-- Header -->
 <div th:replace="header :: header"></div>
 
-<!-- Platform Section -->
-<div th:class="local">
-    <span class="platform-flag" th:text="local"></span>
+<div th:class="alibaba-platform">
+    <span class="platform-flag" th:text="AlibabaCloud"></span>
 </div>
 
 <main role="main" class="order">
@@ -67,7 +66,7 @@
             <div class="col-6 pl-md-0">
                 Total Paid
             </div>
-            <div class="col-6 pr-md-0 text-right" 
th:text="${#numbers.formatDecimal(total_paid, 1, 'COMMA', 2, 'POINT')}">
+            <div class="col-6 pr-md-0 text-right" th:text="'$ ' 
+${total_cost.units + (total_cost.nanos / 1000000000.0)}">
                 <!-- Total Paid -->
             </div>
         </div>
@@ -79,7 +78,10 @@
             </div>
         </div>
     </section>
-
+    <!-- 如果有推荐内容 -->
+    <div th:if="${recommendations != null}">
+        <div th:replace="recommendations :: recommendations"></div>
+    </div>
 </main>
 
 <!-- Footer -->
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/product.html 
b/online_bontique_demo/frontend/src/main/resources/templates/product.html
index f13667e75..69836f22f 100644
--- a/online_bontique_demo/frontend/src/main/resources/templates/product.html
+++ b/online_bontique_demo/frontend/src/main/resources/templates/product.html
@@ -25,42 +25,49 @@
   <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css";>
   <!-- 引用你的 CSS 文件 -->
 </head>
+<div th:class="alibaba-platform">
+    <span class="platform-flag" th:text="AlibabaCloud"></span>
+</div>
 <body>
 <div th:replace="header :: header"></div>
 <main role="main">
-  <div class="h-product container">
-    <div class="row" th:each="prod : ${products}">
-      <div class="col-md-6">
-        <img class="product-image" th:src="@{${prod.picture}}" alt=""/>
-      </div>
-      <div class="product-info col-md-5">
-        <div class="product-wrapper">
-          <h2 th:text="${prod.name}"></h2>
-          <p th:text="${prod.description}"></p>
-
-          <form method="POST" action="/cart/add">
-            <input type="hidden" name="productId" th:value="${prod.id}" />
-            <input type="hidden" name="userId" value="1" />
-            <div class="product-quantity-dropdown">
-              <select name="quantity" id="quantity">
-                <option>1</option>
-                <option>2</option>
-                <option>3</option>
-                <option>4</option>
-                <option>5</option>
-                <option>10</option>
-              </select>
+    <div class="h-product container">
+        <div class="row">
+            <div class="col-md-6">
+                <img class="product-image" alt="" 
th:src="@{${product.picture}}"/>
             </div>
-            <button type="submit" class="cymbal-button-primary">Add To 
Cart</button>
-          </form>
-
+            <div class="product-info col-md-5">
+                <div class="product-wrapper">
+                    <h2 th:text="${product.name}"></h2>
+                    <p th:text="${product.description}"></p>
 
+                    <form method="POST" action="/cart/add">
+                        <input type="hidden" name="productId" 
th:value="${product.id}"/>
+                        <input type="hidden" name="userId" value="1"/>
+                        <div class="product-quantity-dropdown">
+                            <select name="quantity" id="quantity">
+                                <option>1</option>
+                                <option>2</option>
+                                <option>3</option>
+                                <option>4</option>
+                                <option>5</option>
+                                <option>10</option>
+                            </select>
+                            <img src="/static/icons/Hipster_DownArrow.svg" 
alt="">
+                        </div>
+                        <button type="submit" 
class="cymbal-button-primary">Add To Cart</button>
+                    </form>
+                </div>
+            </div>
         </div>
-      </div>
     </div>
-  </div>
 
-  <div class="ad" th:if="${ad}">
+    <!-- 如果有推荐内容 -->
+    <div th:if="${recommendations != null}">
+        <div th:replace="recommendations :: recommendations"></div>
+    </div>
+
+    <div class="ad" th:if="${ad}">
     <div th:fragment="text_ad">
       <div class="container py-3 px-lg-5 py-lg-5">
         <div role="alert">
diff --git 
a/online_bontique_demo/frontend/src/main/resources/templates/recommendations.html
 
b/online_bontique_demo/frontend/src/main/resources/templates/recommendations.html
index daaa0790e..1d6f98cfb 100644
--- 
a/online_bontique_demo/frontend/src/main/resources/templates/recommendations.html
+++ 
b/online_bontique_demo/frontend/src/main/resources/templates/recommendations.html
@@ -31,9 +31,9 @@
         <div class="row">
           <div th:each="recommendation : ${recommendations}" class="col-md-3">
               <div>
-                <a href="/products">
+                  <a th:href="@{|/product/${recommendation.id}|}">
                   <img th:src="${recommendation.picture}" alt="">
-                </a>
+                  </a>
                 <div>
                   <h5 th:text="${recommendation.name}"></h5>
                 </div>
diff --git 
a/online_bontique_demo/productCatalogsService/src/main/java/org/apache/dubbo/shop/service/productcatalogs/ProductCatalogServiceImpl.java
 
b/online_bontique_demo/productCatalogsService/src/main/java/org/apache/dubbo/shop/service/productcatalogs/ProductCatalogServiceImpl.java
index cf8df09a2..3b54d890d 100644
--- 
a/online_bontique_demo/productCatalogsService/src/main/java/org/apache/dubbo/shop/service/productcatalogs/ProductCatalogServiceImpl.java
+++ 
b/online_bontique_demo/productCatalogsService/src/main/java/org/apache/dubbo/shop/service/productcatalogs/ProductCatalogServiceImpl.java
@@ -37,19 +37,19 @@ import java.util.List;
 @DubboService
 @Service
 public class ProductCatalogServiceImpl implements ProductCatalogService, 
Serializable {
-    
+
     private List<Product> products = new ArrayList<>();
-    
+
     // Load products from JSON file
     {
         loadProductsFromJson();
     }
-    
+
     @Override
     public ListProductsResponse listProducts(Empty request) {
         return new ListProductsResponse(products);
     }
-    
+
     @Override
     public Product getProduct(GetProductRequest request) {
         return products.stream()
@@ -57,7 +57,7 @@ public class ProductCatalogServiceImpl implements 
ProductCatalogService, Seriali
                 .findFirst()
                 .orElse(null);
     }
-    
+
     private void loadProductsFromJson() {
         ObjectMapper objectMapper = new ObjectMapper();
         try {
@@ -68,11 +68,10 @@ public class ProductCatalogServiceImpl implements 
ProductCatalogService, Seriali
             e.printStackTrace();
         }
     }
-    
+
     // 内部类用于解析JSON
     @Data
     public static class ProductsWrapper {
-        
         private List<Product> products;
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to