Compare commits
3 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ad3d2fba0c | 5 months ago |
|
|
a846aa28f6 | 5 months ago |
|
|
56b4000464 | 5 months ago |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/demo/demo.iml" filepath="$PROJECT_DIR$/demo/demo.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/project.iml" filepath="$PROJECT_DIR$/project.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@ -0,0 +1,5 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
// main/Main.java (程序入口)
|
||||
package main;
|
||||
|
||||
import view.MainFrame;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// 仅负责启动主窗口,所有界面逻辑在 view 包中实现
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
MainFrame mainFrame = new MainFrame(); // 这里使用的是 view.MainFrame
|
||||
mainFrame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class Order {
|
||||
private final int id;
|
||||
private final Date orderDate;
|
||||
private final List<OrderItem> orderItems;
|
||||
private final double totalAmount;
|
||||
|
||||
public Order(int id, Date orderDate, List<OrderItem> orderItems, double totalAmount) {
|
||||
this.id = id;
|
||||
this.orderDate = orderDate;
|
||||
this.orderItems = orderItems;
|
||||
this.totalAmount = totalAmount;
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public int getId() { return id; }
|
||||
public Date getOrderDate() { return orderDate; }
|
||||
public List<OrderItem> getOrderItems() { return orderItems; }
|
||||
public double getTotalAmount() { return totalAmount; }
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package model;
|
||||
|
||||
public class OrderItem {
|
||||
private final int productId;
|
||||
private final String productName;
|
||||
private final double price;
|
||||
private final int quantity;
|
||||
private final double subtotal;
|
||||
|
||||
public OrderItem(int productId, String productName, double price, int quantity, double subtotal) {
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.price = price;
|
||||
this.quantity = quantity;
|
||||
this.subtotal = subtotal;
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public int getProductId() { return productId; }
|
||||
public String getProductName() { return productName; }
|
||||
public double getPrice() { return price; }
|
||||
public int getQuantity() { return quantity; }
|
||||
public double getSubtotal() { return subtotal; }
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package model;
|
||||
|
||||
public class Product {
|
||||
private int id;
|
||||
private String name;
|
||||
private double price;
|
||||
private String description;
|
||||
private int stock; // 库存数量
|
||||
|
||||
// 构造函数
|
||||
public Product(int id, String name, double price, String description, int stock) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.price = price;
|
||||
this.description = description;
|
||||
this.stock = stock;
|
||||
}
|
||||
|
||||
// Getter 和 Setter 方法
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int getStock() {
|
||||
return stock;
|
||||
}
|
||||
|
||||
public void setStock(int stock) {
|
||||
this.stock = stock;
|
||||
}
|
||||
|
||||
// 其他方法...
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
package model;
|
||||
|
||||
public class test {
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
package service;
|
||||
|
||||
import model.CartItem;
|
||||
import model.Order;
|
||||
import model.OrderItem;
|
||||
import model.Product;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class OrderService {
|
||||
private final List<Order> orders = new ArrayList<>();
|
||||
private final AtomicInteger orderIdCounter = new AtomicInteger(1); // 订单ID计数器
|
||||
|
||||
/**
|
||||
* 创建新订单
|
||||
* @param cartItems 购物车商品列表
|
||||
* @return 创建的订单
|
||||
* @throws IllegalArgumentException 如果购物车为空
|
||||
* @throws IllegalStateException 如果库存不足
|
||||
*/
|
||||
public Order createOrder(List<CartItem> cartItems) {
|
||||
if (cartItems == null || cartItems.isEmpty()) {
|
||||
throw new IllegalArgumentException("购物车为空,无法创建订单");
|
||||
}
|
||||
|
||||
// 1. 检查所有商品库存是否充足
|
||||
for (CartItem item : cartItems) {
|
||||
Product product = item.getProduct();
|
||||
if (product.getStock() < item.getQuantity()) {
|
||||
throw new IllegalStateException(
|
||||
String.format("商品 '%s' 库存不足,当前库存: %d, 需要: %d",
|
||||
product.getName(), product.getStock(), item.getQuantity()));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 扣减库存
|
||||
for (CartItem item : cartItems) {
|
||||
Product product = item.getProduct();
|
||||
product.setStock(product.getStock() - item.getQuantity());
|
||||
}
|
||||
|
||||
// 3. 创建订单项目列表
|
||||
List<OrderItem> orderItems = new ArrayList<>();
|
||||
for (CartItem cartItem : cartItems) {
|
||||
orderItems.add(new OrderItem(
|
||||
cartItem.getProduct().getId(),
|
||||
cartItem.getProduct().getName(),
|
||||
cartItem.getProduct().getPrice(),
|
||||
cartItem.getQuantity(),
|
||||
cartItem.getSubtotal()
|
||||
));
|
||||
}
|
||||
|
||||
// 4. 创建新订单
|
||||
int orderId = orderIdCounter.getAndIncrement();
|
||||
Order newOrder = new Order(
|
||||
orderId,
|
||||
new Date(), // 订单创建时间
|
||||
orderItems,
|
||||
calculateTotal(orderItems) // 计算订单总金额
|
||||
);
|
||||
|
||||
// 5. 保存订单
|
||||
orders.add(newOrder);
|
||||
return newOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算订单总金额
|
||||
*/
|
||||
private double calculateTotal(List<OrderItem> orderItems) {
|
||||
return orderItems.stream()
|
||||
.mapToDouble(OrderItem::getSubtotal)
|
||||
.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有订单
|
||||
*/
|
||||
public List<Order> getAllOrders() {
|
||||
return new ArrayList<>(orders); // 返回副本,防止外部修改
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID获取订单
|
||||
*/
|
||||
public Order getOrderById(int orderId) {
|
||||
return orders.stream()
|
||||
.filter(order -> order.getId() == orderId)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package service;
|
||||
|
||||
import model.Product;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ProductService {
|
||||
private final List<Product> products;
|
||||
|
||||
public ProductService() {
|
||||
this.products = new ArrayList<>();
|
||||
initializeSampleProducts();
|
||||
}
|
||||
|
||||
private void initializeSampleProducts() {
|
||||
// 初始化一些示例商品
|
||||
addProduct(new Product(1, "MacBook Pro", 12999.00, "13英寸 M1芯片 8核CPU 8核GPU", 50));
|
||||
addProduct(new Product(2, "iPhone 13", 5999.00, "6.1英寸 Super Retina XDR 显示屏", 100));
|
||||
addProduct(new Product(3, "AirPods Pro", 1999.00, "主动降噪无线蓝牙耳机", 200));
|
||||
addProduct(new Product(4, "iPad Air", 4799.00, "10.9英寸 Liquid 视网膜显示屏", 80));
|
||||
addProduct(new Product(5, "Apple Watch Series 7", 2999.00, "45毫米 GPS 款", 120));
|
||||
}
|
||||
|
||||
public List<Product> getAllProducts() {
|
||||
return new ArrayList<>(products); // 返回副本以避免外部修改
|
||||
}
|
||||
|
||||
public Product getProductById(int id) {
|
||||
return products.stream()
|
||||
.filter(p -> p.getId() == id)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public void addProduct(Product product) {
|
||||
if (product != null && !products.contains(product)) {
|
||||
products.add(product);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateProductStock(int productId, int quantityChange) {
|
||||
Product product = getProductById(productId);
|
||||
if (product != null) {
|
||||
int newStock = product.getStock() + quantityChange;
|
||||
if (newStock >= 0) {
|
||||
product.setStock(newStock);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,191 @@
|
||||
package view;
|
||||
|
||||
import model.CartItem;
|
||||
import model.Product;
|
||||
import service.OrderService;
|
||||
import service.ShoppingCartService;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.List;
|
||||
|
||||
public class CartPanel extends JPanel {
|
||||
private final ShoppingCartService cartService;
|
||||
private final OrderService orderService;
|
||||
private JTable cartTable;
|
||||
private JButton removeButton;
|
||||
private JButton checkoutButton;
|
||||
private JLabel totalLabel;
|
||||
private MainFrame mainFrame;
|
||||
|
||||
public CartPanel(ShoppingCartService cartService, OrderService orderService, MainFrame mainFrame) {
|
||||
this.cartService = cartService;
|
||||
this.orderService = orderService;
|
||||
this.mainFrame = mainFrame;
|
||||
initComponents();
|
||||
layoutComponents(); // 调用布局方法(之前缺失实现)
|
||||
updateCartDisplay();
|
||||
}
|
||||
|
||||
// ✅ 确保此方法是 public 的
|
||||
public void updateCartDisplay() {
|
||||
((CartTableModel) cartTable.getModel()).setCartItems(cartService.getCartItems());
|
||||
totalLabel.setText(String.format("总金额: ¥%.2f", cartService.getTotalAmount()));
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
cartTable = new JTable(new CartTableModel());
|
||||
cartTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
// ✅ 修复:使用静态内部类或独立类作为渲染器
|
||||
cartTable.getColumnModel().getColumn(1).setCellRenderer(new CurrencyRenderer());
|
||||
cartTable.getColumnModel().getColumn(3).setCellRenderer(new CurrencyRenderer());
|
||||
|
||||
removeButton = new JButton("移除选中商品");
|
||||
removeButton.addActionListener(this::removeSelectedItem); // ✅ 实现此方法
|
||||
|
||||
checkoutButton = new JButton("结算");
|
||||
checkoutButton.addActionListener(this::checkout);
|
||||
|
||||
totalLabel = new JLabel("总金额: ¥0.00");
|
||||
}
|
||||
|
||||
// ✅ 添加缺失的 layoutComponents() 方法实现
|
||||
private void layoutComponents() {
|
||||
setLayout(new BorderLayout(10, 10));
|
||||
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
// 添加表格滚动面板
|
||||
add(new JScrollPane(cartTable), BorderLayout.CENTER);
|
||||
|
||||
// 底部控制面板
|
||||
JPanel controlPanel = new JPanel(new BorderLayout(10, 10));
|
||||
|
||||
// 按钮面板
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
buttonPanel.add(removeButton);
|
||||
buttonPanel.add(checkoutButton);
|
||||
|
||||
// 总金额标签
|
||||
JPanel totalPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
totalPanel.add(totalLabel);
|
||||
|
||||
// 组装控制面板
|
||||
controlPanel.add(buttonPanel, BorderLayout.WEST);
|
||||
controlPanel.add(totalPanel, BorderLayout.EAST);
|
||||
|
||||
add(controlPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
// ✅ 实现之前缺失的 removeSelectedItem 方法
|
||||
private void removeSelectedItem(ActionEvent e) {
|
||||
int selectedRow = cartTable.getSelectedRow();
|
||||
if (selectedRow >= 0) {
|
||||
CartItem item = ((CartTableModel) cartTable.getModel()).getItemAt(selectedRow);
|
||||
cartService.removeItem(item.getProduct().getId()); // 假设 ShoppingCartService 有此方法
|
||||
updateCartDisplay();
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(this, "请先选择要移除的商品", "警告", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkout(ActionEvent e) {
|
||||
if (cartService.getCartItems().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this, "购物车为空,无法结算", "警告", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
int confirm = JOptionPane.showConfirmDialog(this,
|
||||
"确认结算购物车中的商品吗?", "确认结算",
|
||||
JOptionPane.YES_NO_OPTION);
|
||||
|
||||
if (confirm == JOptionPane.YES_OPTION) {
|
||||
try {
|
||||
orderService.createOrder(cartService.getCartItems());
|
||||
cartService.clearCart();
|
||||
updateCartDisplay();
|
||||
|
||||
if (mainFrame != null) {
|
||||
mainFrame.refreshProductList();
|
||||
mainFrame.refreshOrderList();
|
||||
}
|
||||
|
||||
JOptionPane.showMessageDialog(this, "订单已创建", "成功", JOptionPane.INFORMATION_MESSAGE);
|
||||
} catch (Exception ex) {
|
||||
JOptionPane.showMessageDialog(this, "结算失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 修复:使用静态内部类作为渲染器,解决访问权限问题
|
||||
private static class CurrencyRenderer extends DefaultTableCellRenderer { // 改为静态内部类
|
||||
private final DecimalFormat currencyFormat = new DecimalFormat("¥#,##0.00");
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus,
|
||||
int row, int column) {
|
||||
if (value instanceof Number) {
|
||||
value = currencyFormat.format(value);
|
||||
}
|
||||
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
}
|
||||
}
|
||||
|
||||
private class CartTableModel extends AbstractTableModel {
|
||||
private List<CartItem> cartItems;
|
||||
private final String[] columnNames = {"商品名称", "单价", "数量", "小计", "操作"};
|
||||
|
||||
public void setCartItems(List<CartItem> cartItems) {
|
||||
this.cartItems = cartItems;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public CartItem getItemAt(int row) {
|
||||
return cartItems.get(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return cartItems == null ? 0 : cartItems.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return columnNames.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
return columnNames[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int row, int column) {
|
||||
CartItem item = cartItems.get(row);
|
||||
Product product = item.getProduct(); // 需要 CartItem 有 getProduct() 方法
|
||||
switch (column) {
|
||||
case 0: return product.getName();
|
||||
case 1: return product.getPrice(); // 返回 Double 类型
|
||||
case 2: return item.getQuantity(); // 返回 Integer 类型
|
||||
case 3: return item.getSubtotal(); // 返回 Double 类型
|
||||
case 4: return "移除";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case 1: return Double.class;
|
||||
case 2: return Integer.class;
|
||||
case 3: return Double.class;
|
||||
default: return String.class;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package view;
|
||||
|
||||
import service.OrderService;
|
||||
import service.ProductService;
|
||||
import service.ShoppingCartService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class MainFrame extends JFrame {
|
||||
private final ProductService productService;
|
||||
private final ShoppingCartService cartService;
|
||||
private final OrderService orderService;
|
||||
|
||||
private ProductPanel productPanel;
|
||||
private CartPanel cartPanel;
|
||||
private OrderPanel orderPanel; // 新增:订单面板引用
|
||||
|
||||
public MainFrame() {
|
||||
this.productService = new ProductService();
|
||||
this.cartService = new ShoppingCartService();
|
||||
this.orderService = new OrderService();
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("在线购物平台");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(900, 700);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
createPanels();
|
||||
setupTabbedPane();
|
||||
setupMenuBar();
|
||||
|
||||
add(tabbedPane, BorderLayout.CENTER);
|
||||
}
|
||||
private void createPanels() {
|
||||
this.productPanel = new ProductPanel(productService, cartService, this);
|
||||
this.cartPanel = new CartPanel(cartService, orderService, this); // 正确初始化 CartPanel
|
||||
this.orderPanel = new OrderPanel(orderService);
|
||||
}
|
||||
|
||||
|
||||
private final JTabbedPane tabbedPane = new JTabbedPane();
|
||||
private void setupTabbedPane() { // 修改此方法
|
||||
tabbedPane.addTab("商品展示", new JScrollPane(productPanel));
|
||||
tabbedPane.addTab("购物车", new JScrollPane(cartPanel));
|
||||
tabbedPane.addTab("订单管理", new JScrollPane(orderPanel)); // 新增订单标签页
|
||||
}
|
||||
|
||||
private void setupMenuBar() { // 保持不变
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
JMenu fileMenu = new JMenu("文件");
|
||||
|
||||
JMenuItem exitItem = new JMenuItem("退出");
|
||||
|
||||
exitItem.addActionListener(e -> System.exit(0));
|
||||
fileMenu.add(exitItem);
|
||||
menuBar.add(fileMenu);
|
||||
|
||||
setJMenuBar(menuBar);
|
||||
|
||||
}
|
||||
|
||||
// 新增以下刷新方法
|
||||
public void refreshOrderList() { // 添加此新方法
|
||||
if (orderPanel != null) { // 确保订单面板已初始化
|
||||
orderPanel.refreshOrderList();
|
||||
}
|
||||
}
|
||||
|
||||
// 原有刷新方法保持不变...
|
||||
// ✅ 确保调用 CartPanel 的 public 方法 updateCartDisplay()
|
||||
public void refreshCartDisplay() {
|
||||
if (cartPanel != null) {
|
||||
cartPanel.updateCartDisplay(); // 现在可以正确访问,因为方法是 public 的
|
||||
} else {
|
||||
System.err.println("CartPanel 未初始化");
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshProductList() { // 已存在
|
||||
if (productPanel != null) productPanel.refreshProductList();
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,151 @@
|
||||
package view;
|
||||
|
||||
import model.Order;
|
||||
import model.OrderItem;
|
||||
import service.OrderService;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class OrderPanel extends JPanel {
|
||||
private final OrderService orderService;
|
||||
private JTable orderTable;
|
||||
private JTable orderItemsTable;
|
||||
private OrderTableModel orderTableModel;
|
||||
|
||||
public OrderPanel(OrderService orderService) {
|
||||
this.orderService = orderService;
|
||||
initComponents();
|
||||
layoutComponents();
|
||||
refreshOrderList();
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
orderTableModel = new OrderTableModel();
|
||||
orderTable = new JTable(orderTableModel);
|
||||
orderTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
orderTable.getSelectionModel().addListSelectionListener(e -> {
|
||||
if (!e.getValueIsAdjusting()) {
|
||||
showSelectedOrderItems();
|
||||
}
|
||||
});
|
||||
|
||||
orderItemsTable = new JTable(new OrderItemsTableModel());
|
||||
}
|
||||
|
||||
private void layoutComponents() {
|
||||
setLayout(new BorderLayout(10, 10));
|
||||
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
JLabel titleLabel = new JLabel("订单管理");
|
||||
titleLabel.setFont(new Font("Arial", Font.BOLD, 18));
|
||||
add(titleLabel, BorderLayout.NORTH);
|
||||
|
||||
JPanel orderListPanel = new JPanel(new BorderLayout());
|
||||
orderListPanel.setBorder(BorderFactory.createTitledBorder("订单列表"));
|
||||
orderListPanel.add(new JScrollPane(orderTable), BorderLayout.CENTER);
|
||||
|
||||
JPanel orderItemsPanel = new JPanel(new BorderLayout());
|
||||
orderItemsPanel.setBorder(BorderFactory.createTitledBorder("订单商品明细"));
|
||||
orderItemsPanel.add(new JScrollPane(orderItemsTable), BorderLayout.CENTER);
|
||||
|
||||
add(orderListPanel, BorderLayout.CENTER);
|
||||
add(orderItemsPanel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public void refreshOrderList() {
|
||||
List<Order> orders = orderService.getAllOrders();
|
||||
orderTableModel.setOrders(orders);
|
||||
}
|
||||
|
||||
private void showSelectedOrderItems() {
|
||||
int selectedRow = orderTable.getSelectedRow();
|
||||
if (selectedRow >= 0) {
|
||||
Order selectedOrder = orderTableModel.getOrderAt(selectedRow);
|
||||
((OrderItemsTableModel) orderItemsTable.getModel()).setOrderItems(selectedOrder.getOrderItems());
|
||||
} else {
|
||||
((OrderItemsTableModel) orderItemsTable.getModel()).setOrderItems(null);
|
||||
}
|
||||
}
|
||||
|
||||
private class OrderTableModel extends AbstractTableModel {
|
||||
private List<Order> orders;
|
||||
private final String[] columnNames = {"订单ID", "订单日期", "总金额", "状态"};
|
||||
|
||||
public void setOrders(List<Order> orders) {
|
||||
this.orders = orders;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public Order getOrderAt(int row) {
|
||||
return orders.get(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return orders == null ? 0 : orders.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return columnNames.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
return columnNames[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int row, int column) {
|
||||
Order order = orders.get(row);
|
||||
switch (column) {
|
||||
case 0: return order.getId();
|
||||
case 1: return order.getOrderDate();
|
||||
case 2: return String.format("¥%.2f", order.getTotalAmount());
|
||||
case 3: return "已完成";
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class OrderItemsTableModel extends AbstractTableModel {
|
||||
private List<OrderItem> orderItems;
|
||||
private final String[] columnNames = {"商品ID", "商品名称", "单价", "数量", "小计"};
|
||||
|
||||
public void setOrderItems(List<OrderItem> orderItems) {
|
||||
this.orderItems = orderItems;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return orderItems == null ? 0 : orderItems.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return columnNames.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
return columnNames[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int row, int column) {
|
||||
OrderItem item = orderItems.get(row);
|
||||
switch (column) {
|
||||
case 0: return item.getProductId();
|
||||
case 1: return item.getProductName();
|
||||
case 2: return String.format("¥%.2f", item.getPrice());
|
||||
case 3: return item.getQuantity();
|
||||
case 4: return String.format("¥%.2f", item.getSubtotal());
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@ -0,0 +1,5 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue