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]