Compare commits

...

3 Commits
main ... src

Author SHA1 Message Date
test ad3d2fba0c project
5 months ago
test a846aa28f6 1.6 txt
5 months ago
test 56b4000464 1.6 txt
5 months ago

@ -1 +1 @@
12 124462525

29
project/.gitignore vendored

@ -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,31 @@
package model;
public class CartItem {
private final Product product;
private int quantity;
public CartItem(Product product, int quantity) {
this.product = product;
this.quantity = quantity;
}
// 获取商品
public Product getProduct() {
return product;
}
// 获取数量
public int getQuantity() {
return quantity;
}
// 设置数量
public void setQuantity(int quantity) {
this.quantity = quantity;
}
// 计算小计金额(修复:方法名应为 getSubtotal 而非 getItemTotal
public double getSubtotal() {
return product.getPrice() * quantity;
}
}

@ -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,54 @@
package service;
import model.CartItem;
import model.Product;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCartService {
private final List<CartItem> cartItems = new ArrayList<>();
// 添加商品到购物车
public void addItem(Product product, int quantity) {
// 检查商品是否已在购物车中
for (CartItem item : cartItems) {
if (item.getProduct().getId() == product.getId()) {
item.setQuantity(item.getQuantity() + quantity);
return;
}
}
cartItems.add(new CartItem(product, quantity));
}
// 从购物车移除商品(修复:方法名应为 removeItem 而非 removeFromCart
public void removeItem(int productId) {
cartItems.removeIf(item -> item.getProduct().getId() == productId);
}
// 更新购物车商品数量
public void updateQuantity(int productId, int quantity) {
for (CartItem item : cartItems) {
if (item.getProduct().getId() == productId) {
item.setQuantity(quantity);
break;
}
}
}
// 获取购物车所有商品
public List<CartItem> getCartItems() {
return new ArrayList<>(cartItems);
}
// 清空购物车
public void clearCart() {
cartItems.clear();
}
// 计算购物车总金额
public double getTotalAmount() {
return cartItems.stream()
.mapToDouble(CartItem::getSubtotal) // 使用 CartItem 的 getSubtotal 方法
.sum();
}
}

@ -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,209 @@
package view;
import model.Product;
import service.ProductService;
import service.ShoppingCartService;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class ProductPanel extends JPanel {
private final ProductService productService;
private final ShoppingCartService cartService;
private final MainFrame mainFrame; // 用于刷新购物车面板
private JTable productTable;
private ProductTableModel productTableModel;
private JTextField quantityField;
public ProductPanel(ProductService productService,
ShoppingCartService cartService,
MainFrame mainFrame) {
this.productService = productService;
this.cartService = cartService;
this.mainFrame = mainFrame;
initComponents();
layoutComponents();
refreshProductList(); // 初始加载商品列表
}
private void initComponents() {
// 创建表格模型和表格
productTableModel = new ProductTableModel();
productTable = new JTable(productTableModel);
productTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
productTable.setFillsViewportHeight(true);
// 设置表格列宽
productTable.getColumnModel().getColumn(0).setPreferredWidth(50); // ID
productTable.getColumnModel().getColumn(1).setPreferredWidth(200); // 商品名称
productTable.getColumnModel().getColumn(2).setPreferredWidth(100); // 单价
productTable.getColumnModel().getColumn(3).setPreferredWidth(80); // 库存
// 数量输入框和添加按钮
quantityField = new JTextField(5);
quantityField.setText("1"); // 默认数量1
JButton addToCartButton = new JButton("添加到购物车");
addToCartButton.addActionListener(new AddToCartListener());
// 为数量输入框添加数字验证
quantityField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
char c = evt.getKeyChar();
if (!(Character.isDigit(c) || (c == '\b'))) {
evt.consume(); // 只允许数字和退格键
}
}
});
}
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);
// 中间表格
JScrollPane tableScrollPane = new JScrollPane(productTable);
tableScrollPane.setBorder(BorderFactory.createTitledBorder("可用商品"));
add(tableScrollPane, BorderLayout.CENTER);
// 底部操作区
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
bottomPanel.add(new JLabel("购买数量:"));
bottomPanel.add(quantityField);
bottomPanel.add(new JButton("添加到购物车") {{
addActionListener(new AddToCartListener());
}});
add(bottomPanel, BorderLayout.SOUTH);
}
/**
*
*/
public void refreshProductList() {
List<Product> products = productService.getAllProducts();
productTableModel.setProducts(products);
}
/**
*
*/
private class AddToCartListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int selectedRow = productTable.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(ProductPanel.this,
"请先选择一个商品", "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
try {
int quantity = Integer.parseInt(quantityField.getText().trim());
if (quantity <= 0) {
JOptionPane.showMessageDialog(ProductPanel.this,
"请输入有效的数量", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
Product selectedProduct = productTableModel.getProductAt(selectedRow);
// 检查库存
if (selectedProduct.getStock() < quantity) {
JOptionPane.showMessageDialog(ProductPanel.this,
"库存不足!当前库存: " + selectedProduct.getStock(),
"错误", JOptionPane.ERROR_MESSAGE);
return;
}
// 添加到购物车
cartService.addItem(selectedProduct, quantity);
// 显示成功消息
JOptionPane.showMessageDialog(ProductPanel.this,
"已添加 " + selectedProduct.getName() + " x " + quantity + " 到购物车",
"添加成功", JOptionPane.INFORMATION_MESSAGE);
// 通知主窗口刷新购物车面板
mainFrame.refreshCartDisplay();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(ProductPanel.this,
"请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE);
}
}
}
/**
*
*/
private static class ProductTableModel extends AbstractTableModel {
private List<Product> products;
private final String[] columnNames = {"商品ID", "商品名称", "单价 (¥)", "库存数量"};
public void setProducts(List<Product> products) {
this.products = products;
fireTableDataChanged();
}
public Product getProductAt(int row) {
return products.get(row);
}
@Override
public int getRowCount() {
return products == null ? 0 : products.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) {
Product product = products.get(row);
switch (column) {
case 0:
return product.getId(); // Integer
case 1:
return product.getName(); // String
case 2:
return product.getPrice(); // Double (关键:返回原始数字)
case 3:
return product.getStock(); // Integer
default:
return null;
}
}
// 添加getColumnClass方法告诉表格每列的数据类型
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Integer.class; // ID列是整数
case 2:
return Double.class; // 价格列是小数
case 3:
return Integer.class; // 库存列是整数
default:
return String.class; // 默认是字符串
}
}
}
}

@ -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…
Cancel
Save