From 02b48c0250e701b30840032d2fad973062173f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=AD=90=E7=90=A6?= <95332614+wangziqi0409@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:24:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A2=E5=8D=95=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=A4=9A=E9=A1=B9=E9=97=AE=E9=A2=98=EF=BC=9AToken?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E3=80=81=E8=B4=AD=E7=89=A9=E8=BD=A6=E3=80=81?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=88=9B=E5=BB=BA=E3=80=81=E5=8F=91=E8=B4=A7?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cosmetics/config/SaTokenConfig.java | 1 - .../cosmetics/controller/OrderController.java | 54 +- .../cosmetics/controller/UserController.java | 2 + .../com/meiruo/cosmetics/entity/Order.java | 2 + .../meiruo/cosmetics/entity/OrderItem.java | 1 + .../meiruo/cosmetics/mapper/CartMapper.java | 5 +- .../meiruo/cosmetics/mapper/OrderMapper.java | 2 + .../cosmetics/service/OrderService.java | 4 + .../service/impl/OrderServiceImpl.java | 87 + .../src/main/resources/application.yml | 8 +- .../src/main/resources/mapper/CartMapper.xml | 4 + .../main/resources/mapper/OrderItemMapper.xml | 9 +- .../src/main/resources/mapper/OrderMapper.xml | 11 + meiruo-frontend/pnpm-lock.yaml | 1407 +++++++++++++++++ meiruo-frontend/src/api/index.js | 1 + meiruo-frontend/src/components/Footer.vue | 2 +- meiruo-frontend/src/stores/user.js | 7 +- .../src/views/admin/BannerManage.vue | 8 +- .../src/views/admin/OrderManage.vue | 114 +- .../src/views/admin/ProductManage.vue | 8 +- meiruo-frontend/src/views/user/Cart.vue | 10 +- meiruo-frontend/src/views/user/Checkout.vue | 26 +- meiruo-frontend/src/views/user/Home.vue | 10 +- meiruo-frontend/src/views/user/Order.vue | 65 +- .../src/views/user/ProductDetail.vue | 8 +- meiruo-frontend/vite.config.js | 4 + 26 files changed, 1801 insertions(+), 59 deletions(-) create mode 100644 meiruo-frontend/pnpm-lock.yaml diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java index bb9230c..b500d0e 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/config/SaTokenConfig.java @@ -1,7 +1,6 @@ package com.meiruo.cosmetics.config; import cn.dev33.satoken.interceptor.SaInterceptor; -import cn.dev33.satoken.jwt.SaJwtManager; import cn.dev33.satoken.jwt.StpLogicJwtForSimple; import cn.dev33.satoken.stp.StpInterface; import org.springframework.context.annotation.Bean; diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java index 2273eab..fb52baf 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/OrderController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/order") @@ -22,13 +23,36 @@ public class OrderController { @RequestBody Map params) { Map result = new HashMap<>(); Long userId = StpUtil.getLoginIdAsLong(); - List cartIds = (List) params.get("cartIds"); + String receiverName = (String) params.get("receiverName"); String receiverPhone = (String) params.get("receiverPhone"); String receiverAddress = (String) params.get("receiverAddress"); String remark = (String) params.get("remark"); - - Order order = orderService.create(userId, cartIds, receiverName, receiverPhone, receiverAddress, remark); + + // 处理 cartIds 类型转换(前端传来的是 Integer,需要转为 Long) + @SuppressWarnings("unchecked") + List rawCartIds = (List) params.get("cartIds"); + List cartIds = (rawCartIds == null || rawCartIds.isEmpty()) + ? new ArrayList<>() + : rawCartIds.stream() + .map(id -> Long.valueOf(id.toString())) + .collect(Collectors.toList()); + + // 处理直接购买(不传cartIds,传items) + @SuppressWarnings("unchecked") + List> items = (List>) params.get("items"); + + Order order; + if (cartIds != null && !cartIds.isEmpty()) { + order = orderService.create(userId, cartIds, receiverName, receiverPhone, receiverAddress, remark); + } else if (items != null && !items.isEmpty()) { + order = orderService.createDirect(userId, items, receiverName, receiverPhone, receiverAddress, remark); + } else { + result.put("code", 400); + result.put("msg", "购物车为空,无法创建订单"); + return result; + } + result.put("code", 200); result.put("msg", "下单成功"); result.put("data", order); @@ -72,6 +96,30 @@ public class OrderController { return result; } + @PostMapping("/ship/{id}") + public Map shipOrder(@PathVariable Long id, @RequestBody Map params) { + Map result = new HashMap<>(); + String logisticsCompany = params.get("logisticsCompany"); + String trackingNo = params.get("trackingNo"); + + if (logisticsCompany == null || logisticsCompany.trim().isEmpty() || + trackingNo == null || trackingNo.trim().isEmpty()) { + result.put("code", 400); + result.put("msg", "物流公司和物流单号不能为空"); + return result; + } + + boolean success = orderService.shipOrder(id, logisticsCompany, trackingNo); + if (success) { + result.put("code", 200); + result.put("msg", "发货成功"); + } else { + result.put("code", 500); + result.put("msg", "发货失败,订单状态可能不正确"); + } + return result; + } + @GetMapping("/revenue/{type}") public Map getRevenueStatistics(@PathVariable String type) { Map result = new HashMap<>(); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java index 22e2657..f294e68 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/controller/UserController.java @@ -25,12 +25,14 @@ public class UserController { result.put("msg", "用户名或密码错误"); return result; } + String token = StpUtil.getTokenInfo().getTokenValue(); Map data = new HashMap<>(); data.put("id", loginUser.getId()); data.put("username", loginUser.getUsername()); data.put("nickname", loginUser.getNickname()); data.put("avatar", loginUser.getAvatar()); data.put("role", loginUser.getRole()); + data.put("token", token); result.put("code", 200); result.put("msg", "登录成功"); result.put("data", data); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java index fd06cdd..9a331ee 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/Order.java @@ -14,6 +14,8 @@ public class Order { private String receiverName; private String receiverPhone; private String receiverAddress; + private String logisticsCompany; + private String trackingNo; private String remark; private LocalDateTime createTime; private LocalDateTime payTime; diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java index 0d0ba8c..2b8f31a 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/entity/OrderItem.java @@ -13,5 +13,6 @@ public class OrderItem { private String productImage; private BigDecimal price; private Integer quantity; + private BigDecimal totalPrice; private LocalDateTime createTime; } diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java index 082286e..20da0f4 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/CartMapper.java @@ -4,13 +4,16 @@ import com.meiruo.cosmetics.entity.Cart; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; @Mapper public interface CartMapper { + Cart selectById(@Param("id") Long id); + Cart selectByUserAndProduct(@Param("userId") Long userId, @Param("productId") Long productId); - List selectByUserId(@Param("userId") Long userId); + List> selectByUserId(@Param("userId") Long userId); int insert(Cart cart); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java index a3b9450..51742ba 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/mapper/OrderMapper.java @@ -23,6 +23,8 @@ public interface OrderMapper { int updateStatus(@Param("id") Long id, @Param("status") Integer status); + int shipOrder(@Param("id") Long id, @Param("logisticsCompany") String logisticsCompany, @Param("trackingNo") String trackingNo); + List> selectRevenueStatistics(@Param("type") String type); List> selectTopProducts(@Param("limit") Integer limit); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java index dd26395..8816d8c 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/OrderService.java @@ -8,6 +8,8 @@ public interface OrderService { Order create(Long userId, List cartIds, String receiverName, String receiverPhone, String receiverAddress, String remark); + Order createDirect(Long userId, List> items, String receiverName, String receiverPhone, String receiverAddress, String remark); + Order getById(Long id); Order getByOrderNo(String orderNo); @@ -18,6 +20,8 @@ public interface OrderService { void updateStatus(Long id, Integer status); + boolean shipOrder(Long id, String logisticsCompany, String trackingNo); + Map getRevenueStatistics(String type); List> getTopProducts(Integer limit); diff --git a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java index 9e427ba..83efd04 100644 --- a/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java +++ b/meiruo-backend/src/main/java/com/meiruo/cosmetics/service/impl/OrderServiceImpl.java @@ -1,7 +1,10 @@ package com.meiruo.cosmetics.service.impl; +import com.meiruo.cosmetics.entity.Cart; import com.meiruo.cosmetics.entity.Order; import com.meiruo.cosmetics.entity.OrderItem; +import com.meiruo.cosmetics.entity.Product; +import com.meiruo.cosmetics.mapper.CartMapper; import com.meiruo.cosmetics.mapper.OrderItemMapper; import com.meiruo.cosmetics.mapper.OrderMapper; import com.meiruo.cosmetics.mapper.ProductMapper; @@ -11,6 +14,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -25,6 +29,8 @@ public class OrderServiceImpl implements OrderService { private OrderItemMapper orderItemMapper; @Autowired private ProductMapper productMapper; + @Autowired + private CartMapper cartMapper; @Override @Transactional @@ -42,9 +48,29 @@ public class OrderServiceImpl implements OrderService { BigDecimal totalAmount = BigDecimal.ZERO; for (Long cartId : cartIds) { + Cart cart = cartMapper.selectById(cartId); + if (cart == null || !cart.getUserId().equals(userId)) { + continue; + } + Product product = productMapper.selectById(cart.getProductId()); + if (product == null || product.getStatus() != 1) { + continue; + } + + OrderItem item = new OrderItem(); + item.setProductId(product.getId()); + item.setProductName(product.getName()); + item.setProductImage(product.getImage()); + item.setPrice(product.getPrice()); + item.setQuantity(cart.getQuantity()); + item.setTotalPrice(product.getPrice().multiply(new BigDecimal(cart.getQuantity()))); + orderItems.add(item); + + totalAmount = totalAmount.add(item.getTotalPrice()); } order.setTotalAmount(totalAmount); + order.setCreateTime(LocalDateTime.now()); orderMapper.insert(order); for (OrderItem item : orderItems) { @@ -54,6 +80,11 @@ public class OrderServiceImpl implements OrderService { productMapper.incrementSales(item.getProductId(), item.getQuantity()); } + // 删除购物车中的商品 + for (Long cartId : cartIds) { + cartMapper.delete(cartId); + } + return order; } @@ -77,11 +108,67 @@ public class OrderServiceImpl implements OrderService { return orderMapper.selectList(keyword, status); } + @Override + @Transactional + public Order createDirect(Long userId, List> items, String receiverName, String receiverPhone, String receiverAddress, String remark) { + Order order = new Order(); + order.setOrderNo(UUID.randomUUID().toString().replace("-", "")); + order.setUserId(userId); + order.setReceiverName(receiverName); + order.setReceiverPhone(receiverPhone); + order.setReceiverAddress(receiverAddress); + order.setRemark(remark); + order.setStatus(1); + + List orderItems = new ArrayList<>(); + BigDecimal totalAmount = BigDecimal.ZERO; + + for (Map itemData : items) { + Long productId = Long.valueOf(itemData.get("productId").toString()); + Integer quantity = Integer.valueOf(itemData.get("quantity").toString()); + + Product product = productMapper.selectById(productId); + if (product == null || product.getStatus() != 1) { + continue; + } + + OrderItem item = new OrderItem(); + item.setProductId(product.getId()); + item.setProductName(product.getName()); + item.setProductImage(product.getImage()); + item.setPrice(product.getPrice()); + item.setQuantity(quantity); + item.setTotalPrice(product.getPrice().multiply(new BigDecimal(quantity))); + orderItems.add(item); + + totalAmount = totalAmount.add(item.getTotalPrice()); + } + + order.setTotalAmount(totalAmount); + order.setCreateTime(LocalDateTime.now()); + orderMapper.insert(order); + + for (OrderItem item : orderItems) { + item.setOrderId(order.getId()); + orderItemMapper.insert(item); + productMapper.updateStock(item.getProductId(), item.getQuantity()); + productMapper.incrementSales(item.getProductId(), item.getQuantity()); + } + + return order; + } + @Override public void updateStatus(Long id, Integer status) { orderMapper.updateStatus(id, status); } + @Override + public boolean shipOrder(Long id, String logisticsCompany, String trackingNo) { + int result = orderMapper.shipOrder(id, logisticsCompany, trackingNo); + return result > 0; + } + @Override public Map getRevenueStatistics(String type) { List> statistics = orderMapper.selectRevenueStatistics(type); diff --git a/meiruo-backend/src/main/resources/application.yml b/meiruo-backend/src/main/resources/application.yml index 952934e..97e8d87 100644 --- a/meiruo-backend/src/main/resources/application.yml +++ b/meiruo-backend/src/main/resources/application.yml @@ -4,9 +4,13 @@ server: spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/meiruo_cosmetics?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + url: jdbc:mysql://localhost:3307/meiruo_cosmetics?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root - password: root + password: qq5211314 + servlet: + multipart: + max-file-size: 10MB + max-request-size: 10MB mybatis: mapper-locations: classpath:mapper/*.xml diff --git a/meiruo-backend/src/main/resources/mapper/CartMapper.xml b/meiruo-backend/src/main/resources/mapper/CartMapper.xml index 24338e8..1c999b9 100644 --- a/meiruo-backend/src/main/resources/mapper/CartMapper.xml +++ b/meiruo-backend/src/main/resources/mapper/CartMapper.xml @@ -21,6 +21,10 @@ + + diff --git a/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml b/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml index ca7e2d2..d9a2a0c 100644 --- a/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml +++ b/meiruo-backend/src/main/resources/mapper/OrderItemMapper.xml @@ -10,6 +10,7 @@ + @@ -18,15 +19,15 @@ - INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, create_time) - VALUES (#{orderId}, #{productId}, #{productName}, #{productImage}, #{price}, #{quantity}, NOW()) + INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, total_price, create_time) + VALUES (#{orderId}, #{productId}, #{productName}, #{productImage}, #{price}, #{quantity}, #{totalPrice}, NOW()) - INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, create_time) + INSERT INTO order_item (order_id, product_id, product_name, product_image, price, quantity, total_price, create_time) VALUES - (#{item.orderId}, #{item.productId}, #{item.productName}, #{item.productImage}, #{item.price}, #{item.quantity}, NOW()) + (#{item.orderId}, #{item.productId}, #{item.productName}, #{item.productImage}, #{item.price}, #{item.quantity}, #{item.totalPrice}, NOW()) diff --git a/meiruo-backend/src/main/resources/mapper/OrderMapper.xml b/meiruo-backend/src/main/resources/mapper/OrderMapper.xml index e1c0917..8bbacef 100644 --- a/meiruo-backend/src/main/resources/mapper/OrderMapper.xml +++ b/meiruo-backend/src/main/resources/mapper/OrderMapper.xml @@ -11,6 +11,8 @@ + + @@ -78,6 +80,15 @@ WHERE id = #{id} + + UPDATE `order` + SET status = 3, + ship_time = NOW(), + logistics_company = #{logisticsCompany}, + tracking_no = #{trackingNo} + WHERE id = #{id} AND status = 2 + +