Pārlūkot izejas kodu

Revert "代码迁移"

This reverts commit 75fec4ffebeae233acfa6e368e93277c5ec28cfb.
lutong 2 nedēļas atpakaļ
vecāks
revīzija
2b234527d8
98 mainītis faili ar 1015 papildinājumiem un 11822 dzēšanām
  1. 0 17
      alien-dining/doc/wechat-store-tables-ddl.sql
  2. 10 10
      alien-dining/src/main/java/shop/alien/dining/config/CartWebSocketProcess.java
  3. 4 6
      alien-dining/src/main/java/shop/alien/dining/controller/DiningController.java
  4. 1 1
      alien-dining/src/main/java/shop/alien/dining/controller/PaymentController.java
  5. 15 15
      alien-dining/src/main/java/shop/alien/dining/controller/StoreInfoController.java
  6. 56 58
      alien-dining/src/main/java/shop/alien/dining/controller/StoreOrderController.java
  7. 11 11
      alien-dining/src/main/java/shop/alien/dining/service/CartService.java
  8. 2 2
      alien-dining/src/main/java/shop/alien/dining/service/DiningService.java
  9. 10 10
      alien-dining/src/main/java/shop/alien/dining/service/StoreInfoService.java
  10. 19 21
      alien-dining/src/main/java/shop/alien/dining/service/StoreOrderService.java
  11. 147 147
      alien-dining/src/main/java/shop/alien/dining/service/impl/CartServiceImpl.java
  12. 67 71
      alien-dining/src/main/java/shop/alien/dining/service/impl/DiningServiceImpl.java
  13. 2 2
      alien-dining/src/main/java/shop/alien/dining/service/impl/OrderLockServiceImpl.java
  14. 59 59
      alien-dining/src/main/java/shop/alien/dining/service/impl/StoreInfoServiceImpl.java
  15. 254 256
      alien-dining/src/main/java/shop/alien/dining/service/impl/StoreOrderServiceImpl.java
  16. 1 1
      alien-dining/src/main/java/shop/alien/dining/strategy/payment/PaymentStrategy.java
  17. 27 27
      alien-dining/src/main/java/shop/alien/dining/strategy/payment/impl/WeChatPaymentMininProgramStrategyImpl.java
  18. 0 32
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatAddCartItemDTO.java
  19. 0 34
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCartDTO.java
  20. 0 51
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCartItemDTO.java
  21. 0 26
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatChangeTableDTO.java
  22. 0 47
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCreateOrderDTO.java
  23. 0 23
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatStoreInfoWithHomepageCuisinesDTO.java
  24. 0 22
      alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatUpdateOrderCouponDTO.java
  25. 0 30
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatCategoryWithCuisinesVO.java
  26. 0 50
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderChangeLogBatchVO.java
  27. 0 48
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderChangeLogItemVO.java
  28. 0 66
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderConfirmVO.java
  29. 0 33
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderCuisineItemVO.java
  30. 0 74
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderDetailWithChangeLogVO.java
  31. 0 105
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderInfoVO.java
  32. 0 65
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderSettlementVO.java
  33. 0 31
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderSuccessVO.java
  34. 0 25
      alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatStoreOrderPageVO.java
  35. 0 99
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCart.java
  36. 0 88
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCouponUsage.java
  37. 0 143
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisine.java
  38. 0 66
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisineCategory.java
  39. 0 69
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisineCombo.java
  40. 0 141
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrder.java
  41. 0 120
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderChangeLog.java
  42. 0 108
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderDetail.java
  43. 0 76
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderLock.java
  44. 0 177
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStorePaymentConfig.java
  45. 0 98
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreTable.java
  46. 0 78
      alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreTableLog.java
  47. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCartMapper.java
  48. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCouponUsageMapper.java
  49. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineCategoryMapper.java
  50. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineComboMapper.java
  51. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineMapper.java
  52. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderChangeLogMapper.java
  53. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderDetailMapper.java
  54. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderLockMapper.java
  55. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderMapper.java
  56. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStorePaymentConfigMapper.java
  57. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreTableLogMapper.java
  58. 0 10
      alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreTableMapper.java
  59. 0 26
      alien-store/src/main/java/shop/alien/store/annotation/OperationLog.java
  60. 0 22
      alien-store/src/main/java/shop/alien/store/aspect/DiningOperationLogAspect.java
  61. 0 48
      alien-store/src/main/java/shop/alien/store/controller/DiningCollectController.java
  62. 0 307
      alien-store/src/main/java/shop/alien/store/controller/DiningController.java
  63. 0 188
      alien-store/src/main/java/shop/alien/store/controller/DiningCouponController.java
  64. 0 60
      alien-store/src/main/java/shop/alien/store/controller/DiningFileUploadController.java
  65. 57 59
      alien-store/src/main/java/shop/alien/store/controller/DiningServiceController.java
  66. 0 188
      alien-store/src/main/java/shop/alien/store/controller/DiningUserController.java
  67. 0 108
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  68. 0 578
      alien-store/src/main/java/shop/alien/store/controller/StoreOrderController.java
  69. 0 34
      alien-store/src/main/java/shop/alien/store/dto/ChangePhoneDto.java
  70. 0 56
      alien-store/src/main/java/shop/alien/store/dto/UserProfileUpdateDto.java
  71. 0 20
      alien-store/src/main/java/shop/alien/store/dto/VerifyTokenDto.java
  72. 0 29
      alien-store/src/main/java/shop/alien/store/dto/WeChatLoginDto.java
  73. 0 48
      alien-store/src/main/java/shop/alien/store/enums/OrderStatus.java
  74. 0 80
      alien-store/src/main/java/shop/alien/store/feign/AlienStoreFeign.java
  75. 273 0
      alien-store/src/main/java/shop/alien/store/feign/DiningServiceFeign.java
  76. 0 121
      alien-store/src/main/java/shop/alien/store/service/CartService.java
  77. 0 22
      alien-store/src/main/java/shop/alien/store/service/DiningCollectService.java
  78. 0 101
      alien-store/src/main/java/shop/alien/store/service/DiningCouponService.java
  79. 0 150
      alien-store/src/main/java/shop/alien/store/service/DiningService.java
  80. 0 58
      alien-store/src/main/java/shop/alien/store/service/DiningUserService.java
  81. 0 61
      alien-store/src/main/java/shop/alien/store/service/OrderLockService.java
  82. 0 67
      alien-store/src/main/java/shop/alien/store/service/ScanOrderStoreInfoService.java
  83. 0 35
      alien-store/src/main/java/shop/alien/store/service/SseService.java
  84. 0 189
      alien-store/src/main/java/shop/alien/store/service/StoreOrderService.java
  85. 0 1072
      alien-store/src/main/java/shop/alien/store/service/impl/CartServiceImpl.java
  86. 0 39
      alien-store/src/main/java/shop/alien/store/service/impl/DiningCollectServiceImpl.java
  87. 0 471
      alien-store/src/main/java/shop/alien/store/service/impl/DiningCouponServiceImpl.java
  88. 0 690
      alien-store/src/main/java/shop/alien/store/service/impl/DiningServiceImpl.java
  89. 0 697
      alien-store/src/main/java/shop/alien/store/service/impl/DiningUserServiceImpl.java
  90. 0 118
      alien-store/src/main/java/shop/alien/store/service/impl/OrderLockServiceImpl.java
  91. 0 239
      alien-store/src/main/java/shop/alien/store/service/impl/ScanOrderStoreInfoServiceImpl.java
  92. 0 180
      alien-store/src/main/java/shop/alien/store/service/impl/SseServiceImpl.java
  93. 0 2019
      alien-store/src/main/java/shop/alien/store/service/impl/StoreOrderServiceImpl.java
  94. 0 227
      alien-store/src/main/java/shop/alien/store/util/TokenUtil.java
  95. 0 375
      alien-store/src/main/java/shop/alien/store/util/WeChatMiniProgramUtil.java
  96. 0 65
      alien-store/src/main/java/shop/alien/store/util/WeChatPayUtil.java
  97. 0 76
      alien-store/src/main/java/shop/alien/store/vo/DiningUserVo.java
  98. 0 40
      alien-store/src/main/java/shop/alien/store/vo/TokenVerifyVo.java

+ 0 - 17
alien-dining/doc/wechat-store-tables-ddl.sql

@@ -1,17 +0,0 @@
--- 小程序点餐专用表:与 APP 共库不同表,除用户/门店主数据(store_info)/优惠券定义外独立维护。
--- MySQL 5.7+:CREATE TABLE ... LIKE 复制列定义与索引;请在低峰执行并做好备份。
-
-CREATE TABLE IF NOT EXISTS wechat_store_table LIKE store_table;
-CREATE TABLE IF NOT EXISTS wechat_store_cuisine LIKE store_cuisine;
-CREATE TABLE IF NOT EXISTS wechat_store_cuisine_category LIKE store_cuisine_category;
-CREATE TABLE IF NOT EXISTS wechat_store_cuisine_combo LIKE store_cuisine_combo;
-CREATE TABLE IF NOT EXISTS wechat_store_cart LIKE store_cart;
-CREATE TABLE IF NOT EXISTS wechat_store_order LIKE store_order;
-CREATE TABLE IF NOT EXISTS wechat_store_order_detail LIKE store_order_detail;
-CREATE TABLE IF NOT EXISTS wechat_store_order_lock LIKE store_order_lock;
-CREATE TABLE IF NOT EXISTS wechat_store_table_log LIKE store_table_log;
-CREATE TABLE IF NOT EXISTS wechat_store_order_change_log LIKE store_order_change_log;
-CREATE TABLE IF NOT EXISTS wechat_store_coupon_usage LIKE store_coupon_usage;
-CREATE TABLE IF NOT EXISTS wechat_store_payment_config LIKE store_payment_config;
-
--- 上线后需将小程序侧菜单/桌台等基础数据同步或录入到 wechat_* 表(与 APP 侧无数据互通)。

+ 10 - 10
alien-dining/src/main/java/shop/alien/dining/config/CartWebSocketProcess.java

@@ -7,8 +7,8 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.stereotype.Component;
 import shop.alien.dining.service.CartService;
-import shop.alien.entity.store.dto.wechat.WechatAddCartItemDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
+import shop.alien.entity.store.dto.AddCartItemDTO;
+import shop.alien.entity.store.dto.CartDTO;
 
 import javax.websocket.*;
 import javax.websocket.server.PathParam;
@@ -79,7 +79,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
 
             // 发送当前购物车数据
             try {
-                WechatCartDTO cart = cartService.getCart(tableId);
+                CartDTO cart = cartService.getCart(tableId);
                 sendMessage(createMessage("cart_update", "购物车数据", cart));
             } catch (Exception e) {
                 log.error("获取购物车数据失败, tableId={}", tableId, e);
@@ -178,14 +178,14 @@ public class CartWebSocketProcess implements ApplicationContextAware {
                 return;
             }
 
-            WechatAddCartItemDTO dto = new WechatAddCartItemDTO();
+            AddCartItemDTO dto = new AddCartItemDTO();
             dto.setTableId(tableId);
             dto.setCuisineId(data.getInteger("cuisineId"));
             dto.setQuantity(data.getInteger("quantity"));
             dto.setRemark(data.getString("remark"));
 
             // 调用服务添加商品
-            WechatCartDTO cart = cartService.addItem(dto);
+            CartDTO cart = cartService.addItem(dto);
 
             // 推送更新给该桌号的所有连接
             pushCartUpdateToAll(tableId, cart);
@@ -219,7 +219,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
             }
 
             // 调用服务更新数量
-            WechatCartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
+            CartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
 
             // 推送更新给该桌号的所有连接
             pushCartUpdateToAll(tableId, cart);
@@ -251,7 +251,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
             }
 
             // 调用服务删除商品
-            WechatCartDTO cart = cartService.removeItem(tableId, cuisineId);
+            CartDTO cart = cartService.removeItem(tableId, cuisineId);
 
             // 推送更新给该桌号的所有连接
             pushCartUpdateToAll(tableId, cart);
@@ -274,7 +274,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
             cartService.clearCart(tableId);
 
             // 创建空的购物车对象
-            WechatCartDTO cart = new WechatCartDTO();
+            CartDTO cart = new CartDTO();
             cart.setTableId(tableId);
             cart.setItems(java.util.Collections.emptyList());
             cart.setTotalAmount(java.math.BigDecimal.ZERO);
@@ -295,7 +295,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
     /**
      * 推送购物车更新给该桌号的所有连接
      */
-    private void pushCartUpdateToAll(Integer tableId, WechatCartDTO cart) {
+    private void pushCartUpdateToAll(Integer tableId, CartDTO cart) {
         ConcurrentHashMap<String, CartWebSocketProcess> tableConnections = connections.get(tableId);
         if (tableConnections != null && !tableConnections.isEmpty()) {
             tableConnections.forEach((connId, ws) -> {
@@ -359,7 +359,7 @@ public class CartWebSocketProcess implements ApplicationContextAware {
     /**
      * 静态方法:推送购物车更新(供外部调用,如HTTP接口)
      */
-    public static void pushCartUpdate(Integer tableId, WechatCartDTO cart) {
+    public static void pushCartUpdate(Integer tableId, CartDTO cart) {
         ConcurrentHashMap<String, CartWebSocketProcess> tableConnections = connections.get(tableId);
         if (tableConnections != null && !tableConnections.isEmpty()) {
             String message = createStaticMessage("cart_update", "购物车更新", cart);

+ 4 - 6
alien-dining/src/main/java/shop/alien/dining/controller/DiningController.java

@@ -8,8 +8,6 @@ import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.vo.TableDiningStatusVO;
 import shop.alien.entity.store.vo.*;
-import shop.alien.entity.store.vo.wechat.WechatOrderConfirmVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderSettlementVO;
 import shop.alien.dining.service.DiningService;
 import shop.alien.dining.util.TokenUtil;
 
@@ -169,7 +167,7 @@ public class DiningController {
 
     @ApiOperation(value = "获取订单确认页面信息", notes = "获取订单确认页面的所有信息")
     @GetMapping("/order/confirm")
-    public R<WechatOrderConfirmVO> getOrderConfirmInfo(
+    public R<OrderConfirmVO> getOrderConfirmInfo(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "就餐人数", required = true) @RequestParam Integer dinerCount) {
         log.info("DiningController.getOrderConfirmInfo?tableId={}, dinerCount={}", tableId, dinerCount);
@@ -179,7 +177,7 @@ public class DiningController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            WechatOrderConfirmVO vo = diningService.getOrderConfirmInfo(tableId, dinerCount, userId);
+            OrderConfirmVO vo = diningService.getOrderConfirmInfo(tableId, dinerCount, userId);
             return R.data(vo);
         } catch (Exception e) {
             log.error("获取订单确认页面信息失败: {}", e.getMessage(), e);
@@ -249,7 +247,7 @@ public class DiningController {
 
     @ApiOperation(value = "获取订单结算确认页面信息", notes = "获取订单结算确认页面的所有信息")
     @GetMapping("/order/settlement")
-    public R<WechatOrderSettlementVO> getOrderSettlementInfo(
+    public R<shop.alien.entity.store.vo.OrderSettlementVO> getOrderSettlementInfo(
             @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
         log.info("DiningController.getOrderSettlementInfo?orderId={}", orderId);
         try {
@@ -258,7 +256,7 @@ public class DiningController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            WechatOrderSettlementVO vo = diningService.getOrderSettlementInfo(orderId, userId);
+            shop.alien.entity.store.vo.OrderSettlementVO vo = diningService.getOrderSettlementInfo(orderId, userId);
             return R.data(vo);
         } catch (Exception e) {
             log.error("获取订单结算确认页面信息失败: {}", e.getMessage(), e);

+ 1 - 1
alien-dining/src/main/java/shop/alien/dining/controller/PaymentController.java

@@ -44,7 +44,7 @@ public class PaymentController {
             @ApiImplicitParam(name = "payType", value = "支付类型(alipay:支付宝, wechatPay:微信支付)", required = true, paramType = "query", dataType = "String"),
             @ApiImplicitParam(name = "payer", value = "支付用户", required = true, paramType = "query", dataType = "String"),
             @ApiImplicitParam(name = "orderNo", value = "订单号", required = true, paramType = "query", dataType = "String"),
-            @ApiImplicitParam(name = "storeId", value = "店铺ID,用于从 MySQL 获取该店铺支付配置(WechatStorePaymentConfig)", required = true, paramType = "query", dataType = "Integer"),
+            @ApiImplicitParam(name = "storeId", value = "店铺ID,用于从 MySQL 获取该店铺支付配置(StorePaymentConfig)", required = true, paramType = "query", dataType = "Integer"),
             @ApiImplicitParam(name ="couponId", value = "优惠券Id"),
             @ApiImplicitParam(name = "payerId", value = "payerId"),
             @ApiImplicitParam(name = "tablewareFee", value = "餐具费"),

+ 15 - 15
alien-dining/src/main/java/shop/alien/dining/controller/StoreInfoController.java

@@ -5,11 +5,11 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCategory;
-import shop.alien.entity.store.wechat.WechatStoreTable;
-import shop.alien.entity.store.dto.wechat.WechatStoreInfoWithHomepageCuisinesDTO;
-import shop.alien.entity.store.vo.wechat.WechatCategoryWithCuisinesVO;
+import shop.alien.entity.store.StoreCuisine;
+import shop.alien.entity.store.StoreCuisineCategory;
+import shop.alien.entity.store.StoreTable;
+import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
 import shop.alien.dining.service.StoreInfoService;
 
 import java.util.List;
@@ -32,14 +32,14 @@ public class StoreInfoController {
 
     @ApiOperation(value = "根据门店ID查询桌号列表", notes = "查询指定门店下的所有桌号")
     @GetMapping("/tables")
-    public R<List<WechatStoreTable>> getTablesByStoreId(
+    public R<List<StoreTable>> getTablesByStoreId(
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
         log.info("StoreInfoController.getTablesByStoreId?storeId={}", storeId);
         try {
             if (storeId == null) {
                 return R.fail("门店ID不能为空");
             }
-            List<WechatStoreTable> tables = storeInfoService.getTablesByStoreId(storeId);
+            List<StoreTable> tables = storeInfoService.getTablesByStoreId(storeId);
             return R.data(tables);
         } catch (Exception e) {
             log.error("查询桌号列表失败: {}", e.getMessage(), e);
@@ -49,14 +49,14 @@ public class StoreInfoController {
 
     @ApiOperation(value = "根据门店ID查询菜品种类列表", notes = "查询指定门店下的所有菜品种类")
     @GetMapping("/categories")
-    public R<List<WechatStoreCuisineCategory>> getCategoriesByStoreId(
+    public R<List<StoreCuisineCategory>> getCategoriesByStoreId(
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
         log.info("StoreInfoController.getCategoriesByStoreId?storeId={}", storeId);
         try {
             if (storeId == null) {
                 return R.fail("门店ID不能为空");
             }
-            List<WechatStoreCuisineCategory> categories = storeInfoService.getCategoriesByStoreId(storeId);
+            List<StoreCuisineCategory> categories = storeInfoService.getCategoriesByStoreId(storeId);
             return R.data(categories);
         } catch (Exception e) {
             log.error("查询菜品种类列表失败: {}", e.getMessage(), e);
@@ -66,7 +66,7 @@ public class StoreInfoController {
 
     @ApiOperation(value = "根据门店ID查询菜品种类及各类别下菜品", notes = "一次返回所有菜品种类及每个分类下的菜品列表;可选 keyword 按菜品名称模糊查询。返回中 category 与 /store/info/categories 单条结构一致,cuisines 与 /store/info/cuisines 返回结构一致,保证字段完整一致。")
     @GetMapping("/categories-with-cuisines")
-    public R<List<WechatCategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
+    public R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
             @ApiParam(value = "菜品名称模糊查询关键词(可选)") @RequestParam(required = false) String keyword) {
         log.info("StoreInfoController.getCategoriesWithCuisinesByStoreId?storeId={}, keyword={}", storeId, keyword);
@@ -74,7 +74,7 @@ public class StoreInfoController {
             if (storeId == null) {
                 return R.fail("门店ID不能为空");
             }
-            List<WechatCategoryWithCuisinesVO> list = storeInfoService.getCategoriesWithCuisinesByStoreId(storeId, keyword);
+            List<CategoryWithCuisinesVO> list = storeInfoService.getCategoriesWithCuisinesByStoreId(storeId, keyword);
             return R.data(list);
         } catch (Exception e) {
             log.error("查询菜品种类及菜品失败: {}", e.getMessage(), e);
@@ -101,14 +101,14 @@ public class StoreInfoController {
 
     @ApiOperation(value = "根据菜品种类ID查询菜品信息列表", notes = "查询指定分类下的所有菜品信息")
     @GetMapping("/cuisines")
-    public R<List<WechatStoreCuisine>> getCuisinesByCategoryId(
+    public R<List<StoreCuisine>> getCuisinesByCategoryId(
             @ApiParam(value = "菜品种类ID", required = true) @RequestParam Integer categoryId) {
         log.info("StoreInfoController.getCuisinesByCategoryId?categoryId={}", categoryId);
         try {
             if (categoryId == null) {
                 return R.fail("菜品种类ID不能为空");
             }
-            List<WechatStoreCuisine> cuisines = storeInfoService.getCuisinesByCategoryId(categoryId);
+            List<StoreCuisine> cuisines = storeInfoService.getCuisinesByCategoryId(categoryId);
             return R.data(cuisines);
         } catch (Exception e) {
             log.error("查询菜品信息列表失败: {}", e.getMessage(), e);
@@ -118,14 +118,14 @@ public class StoreInfoController {
 
     @ApiOperation(value = "根据商铺ID查询店铺信息和首页展示美食价目表", notes = "查询店铺信息和当前店铺绑定的首页展示美食价目表信息")
     @GetMapping("/detail/{storeId}")
-    public R<WechatStoreInfoWithHomepageCuisinesDTO> getStoreInfoWithHomepageCuisines(
+    public R<StoreInfoWithHomepageCuisinesDTO> getStoreInfoWithHomepageCuisines(
             @ApiParam(value = "商铺ID", required = true) @PathVariable Integer storeId) {
         log.info("StoreInfoController.getStoreInfoWithHomepageCuisines?storeId={}", storeId);
         try {
             if (storeId == null) {
                 return R.fail("商铺ID不能为空");
             }
-            WechatStoreInfoWithHomepageCuisinesDTO result = storeInfoService.getStoreInfoWithHomepageCuisines(storeId);
+            StoreInfoWithHomepageCuisinesDTO result = storeInfoService.getStoreInfoWithHomepageCuisines(storeId);
             return R.data(result);
         } catch (Exception e) {
             log.error("查询店铺信息和首页展示美食价目表失败: {}", e.getMessage(), e);

+ 56 - 58
alien-dining/src/main/java/shop/alien/dining/controller/StoreOrderController.java

@@ -16,19 +16,17 @@ import shop.alien.dining.service.StoreOrderService;
 import shop.alien.dining.util.TokenUtil;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
-import shop.alien.entity.store.wechat.*;
-import shop.alien.entity.store.dto.wechat.WechatAddCartItemDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
-import shop.alien.entity.store.dto.wechat.WechatChangeTableDTO;
-import shop.alien.entity.store.dto.wechat.WechatCreateOrderDTO;
-import shop.alien.entity.store.dto.wechat.WechatUpdateOrderCouponDTO;
-import shop.alien.entity.store.vo.wechat.WechatOrderChangeLogBatchVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderInfoVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderDetailWithChangeLogVO;
-import shop.alien.entity.store.vo.wechat.WechatStoreOrderPageVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderSuccessVO;
+import shop.alien.entity.store.dto.AddCartItemDTO;
+import shop.alien.entity.store.dto.CartDTO;
+import shop.alien.entity.store.dto.ChangeTableDTO;
+import shop.alien.entity.store.dto.CreateOrderDTO;
+import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
+import shop.alien.entity.store.vo.OrderInfoVO;
+import shop.alien.entity.store.vo.OrderDetailWithChangeLogVO;
+import shop.alien.entity.store.vo.StoreOrderPageVO;
 import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.wechat.*;
+import shop.alien.mapper.StoreOrderDetailMapper;
+import shop.alien.mapper.StoreTableMapper;
 
 import javax.validation.Valid;
 import java.util.List;
@@ -50,20 +48,20 @@ public class StoreOrderController {
     private final StoreOrderService orderService;
     private final CartService cartService;
     private final SseService sseService;
-    private final WechatStoreOrderDetailMapper orderDetailMapper;
-    private final WechatStoreTableMapper storeTableMapper;
+    private final StoreOrderDetailMapper orderDetailMapper;
+    private final StoreTableMapper storeTableMapper;
     private final StoreInfoMapper storeInfoMapper;
 
     @ApiOperation(value = "获取购物车", notes = "根据桌号ID获取购物车信息")
     @GetMapping("/cart/{tableId}")
-    public R<WechatCartDTO> getCart(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
+    public R<CartDTO> getCart(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
         log.info("StoreOrderController.getCart?tableId={}", tableId);
         try {
             // 验证 token
             if (!TokenUtil.hasValidToken()) {
                 return R.fail("用户未登录");
             }
-            WechatCartDTO cart = cartService.getCart(tableId);
+            CartDTO cart = cartService.getCart(tableId);
             return R.data(cart);
         } catch (Exception e) {
             log.error("获取购物车失败: {}", e.getMessage(), e);
@@ -73,14 +71,14 @@ public class StoreOrderController {
 
     @ApiOperation(value = "添加商品到购物车", notes = "添加商品到购物车,并推送SSE和WebSocket消息")
     @PostMapping("/cart/add")
-    public R<WechatCartDTO> addCartItem(@Valid @RequestBody WechatAddCartItemDTO dto) {
+    public R<CartDTO> addCartItem(@Valid @RequestBody AddCartItemDTO dto) {
         log.info("StoreOrderController.addCartItem?dto={}", dto);
         try {
             // 验证 token(用户信息在 CartService 中从 token 获取)
             if (!TokenUtil.hasValidToken()) {
                 return R.fail("用户未登录");
             }
-            WechatCartDTO cart = cartService.addItem(dto);
+            CartDTO cart = cartService.addItem(dto);
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(dto.getTableId(), cart);
             // 推送购物车更新消息(WebSocket)
@@ -94,7 +92,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "更新购物车商品数量", notes = "更新购物车中商品的数量,并推送SSE和WebSocket消息")
     @PutMapping("/cart/update")
-    public R<WechatCartDTO> updateCartItem(
+    public R<CartDTO> updateCartItem(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId,
             @ApiParam(value = "数量", required = true) @RequestParam Integer quantity) {
@@ -104,7 +102,7 @@ public class StoreOrderController {
             if (!TokenUtil.hasValidToken()) {
                 return R.fail("用户未登录");
             }
-            WechatCartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
+            CartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(tableId, cart);
             // 推送购物车更新消息(WebSocket)
@@ -118,7 +116,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "删除购物车商品", notes = "从购物车中删除商品,并推送SSE和WebSocket消息")
     @DeleteMapping("/cart/remove")
-    public R<WechatCartDTO> removeCartItem(
+    public R<CartDTO> removeCartItem(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId) {
         log.info("StoreOrderController.removeCartItem?tableId={}, cuisineId={}", tableId, cuisineId);
@@ -127,7 +125,7 @@ public class StoreOrderController {
             if (!TokenUtil.hasValidToken()) {
                 return R.fail("用户未登录");
             }
-            WechatCartDTO cart = cartService.removeItem(tableId, cuisineId);
+            CartDTO cart = cartService.removeItem(tableId, cuisineId);
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(tableId, cart);
             // 推送购物车更新消息(WebSocket)
@@ -141,7 +139,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "清空购物车", notes = "清空购物车中所有商品(保留餐具和已下单商品),并推送SSE和WebSocket消息")
     @DeleteMapping("/cart/clear")
-    public R<WechatCartDTO> clearCart(
+    public R<CartDTO> clearCart(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
         log.info("StoreOrderController.clearCart?tableId={}", tableId);
         try {
@@ -154,7 +152,7 @@ public class StoreOrderController {
             cartService.clearCart(tableId);
             
             // 获取清空后的购物车(包含保留的餐具和已下单商品)
-            WechatCartDTO cart = cartService.getCart(tableId);
+            CartDTO cart = cartService.getCart(tableId);
             
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(tableId, cart);
@@ -170,7 +168,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "设置用餐人数", notes = "设置用餐人数,自动添加或更新餐具到购物车")
     @PostMapping("/cart/set-diner-count")
-    public R<WechatCartDTO> setDinerCount(
+    public R<CartDTO> setDinerCount(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "用餐人数", required = true) @RequestParam Integer dinerCount) {
         log.info("StoreOrderController.setDinerCount?tableId={}, dinerCount={}", tableId, dinerCount);
@@ -182,7 +180,7 @@ public class StoreOrderController {
             if (dinerCount == null || dinerCount <= 0) {
                 return R.fail("用餐人数必须大于0");
             }
-            WechatCartDTO cart = cartService.setDinerCount(tableId, dinerCount);
+            CartDTO cart = cartService.setDinerCount(tableId, dinerCount);
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(tableId, cart);
             // 推送购物车更新消息(WebSocket)
@@ -196,7 +194,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "更新餐具数量", notes = "更新购物车中餐具的数量,并推送SSE和WebSocket消息。餐具数量为0或未传时不往购物车加餐具(0会移除已有餐具项)")
     @PutMapping("/cart/update-tableware")
-    public R<WechatCartDTO> updateTablewareQuantity(
+    public R<CartDTO> updateTablewareQuantity(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "餐具数量,0或未传则不往购物车加餐具") @RequestParam(required = false) Integer quantity) {
         log.info("StoreOrderController.updateTablewareQuantity?tableId={}, quantity={}", tableId, quantity);
@@ -210,16 +208,16 @@ public class StoreOrderController {
             }
             // 餐具数量为 0 或 null 时不往购物车加餐具:0 则移除已有餐具项,null 则直接返回当前购物车
             if (quantity == null) {
-                WechatCartDTO cart = cartService.getCart(tableId);
+                CartDTO cart = cartService.getCart(tableId);
                 sseService.pushCartUpdate(tableId, cart);
                 return R.data(cart);
             }
             if (quantity == 0) {
-                WechatCartDTO cart = cartService.updateTablewareQuantity(tableId, 0);
+                CartDTO cart = cartService.updateTablewareQuantity(tableId, 0);
                 sseService.pushCartUpdate(tableId, cart);
                 return R.data(cart);
             }
-            WechatCartDTO cart = cartService.updateTablewareQuantity(tableId, quantity);
+            CartDTO cart = cartService.updateTablewareQuantity(tableId, quantity);
             // 推送购物车更新消息(SSE)
             sseService.pushCartUpdate(tableId, cart);
             // 推送购物车更新消息(WebSocket)
@@ -233,7 +231,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "创建订单(下单)", notes = "从购物车创建订单,不立即支付。备注:创建/更新时传入,更新订单(加餐)时为覆盖")
     @PostMapping("/create")
-    public R<WechatOrderSuccessVO> createOrder(@Valid @RequestBody WechatCreateOrderDTO dto) {
+    public R<shop.alien.entity.store.vo.OrderSuccessVO> createOrder(@Valid @RequestBody CreateOrderDTO dto) {
         log.info("StoreOrderController.createOrder?dto={}", dto);
         try {
             // 验证 token(用户信息在 StoreOrderService 中从 token 获取)
@@ -247,10 +245,10 @@ public class StoreOrderController {
 
             // 设置不立即支付
             dto.setImmediatePay(0);
-            WechatStoreOrder order = orderService.createOrder(dto);
+            StoreOrder order = orderService.createOrder(dto);
 
             // 转换为OrderSuccessVO
-            WechatOrderSuccessVO vo = new WechatOrderSuccessVO();
+            shop.alien.entity.store.vo.OrderSuccessVO vo = new shop.alien.entity.store.vo.OrderSuccessVO();
             vo.setOrderId(order.getId());
             vo.setOrderNo(order.getOrderNo());
             vo.setTableNumber(order.getTableNumber());
@@ -283,7 +281,7 @@ public class StoreOrderController {
                 return R.fail("用户未登录");
             }
             
-            WechatStoreOrder order = orderService.getOrderById(orderId);
+            StoreOrder order = orderService.getOrderById(orderId);
             if (order == null) {
                 return R.fail("订单不存在");
             }
@@ -331,7 +329,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "查询订单详情", notes = "根据订单ID查询订单详情,包含订单基本信息和按批次分组的变更记录,用于展示每次下单/加餐都加了什么商品")
     @GetMapping("/detail/{orderId}")
-    public R<WechatOrderDetailWithChangeLogVO> getOrderDetail(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
+    public R<OrderDetailWithChangeLogVO> getOrderDetail(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         log.info("StoreOrderController.getOrderDetail?orderId={}", orderId);
         try {
             // 从 token 获取用户信息
@@ -339,7 +337,7 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            WechatOrderDetailWithChangeLogVO orderDetail = orderService.getOrderDetailWithChangeLog(orderId);
+            OrderDetailWithChangeLogVO orderDetail = orderService.getOrderDetailWithChangeLog(orderId);
             return R.data(orderDetail);
         } catch (Exception e) {
             log.error("查询订单详情失败: {}", e.getMessage(), e);
@@ -349,7 +347,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "查询订单明细", notes = "根据订单ID查询订单明细列表")
     @GetMapping("/detail/list/{orderId}")
-    public R<List<WechatStoreOrderDetail>> getOrderDetailList(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
+    public R<List<StoreOrderDetail>> getOrderDetailList(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         log.info("StoreOrderController.getOrderDetailList?orderId={}", orderId);
         try {
             // 从 token 获取用户信息
@@ -357,12 +355,12 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<WechatStoreOrderDetail> wrapper =
+            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StoreOrderDetail> wrapper =
                     new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
-            wrapper.eq(WechatStoreOrderDetail::getOrderId, orderId);
-            wrapper.eq(WechatStoreOrderDetail::getDeleteFlag, 0);
-            wrapper.orderByDesc(WechatStoreOrderDetail::getCreatedTime);
-            List<WechatStoreOrderDetail> details = orderDetailMapper.selectList(wrapper);
+            wrapper.eq(StoreOrderDetail::getOrderId, orderId);
+            wrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
+            wrapper.orderByDesc(StoreOrderDetail::getCreatedTime);
+            List<StoreOrderDetail> details = orderDetailMapper.selectList(wrapper);
             return R.data(details);
         } catch (Exception e) {
             log.error("查询订单明细失败: {}", e.getMessage(), e);
@@ -372,7 +370,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "查询订单信息", notes = "根据订单ID查询订单完整信息(包含订单基本信息、菜品清单、价格明细)")
     @GetMapping("/info/{orderId}")
-    public R<WechatOrderInfoVO> getOrderInfo(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
+    public R<OrderInfoVO> getOrderInfo(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         log.info("StoreOrderController.getOrderInfo?orderId={}", orderId);
         try {
             // 从 token 获取用户信息
@@ -380,7 +378,7 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            WechatOrderInfoVO orderInfo = orderService.getOrderInfo(orderId);
+            OrderInfoVO orderInfo = orderService.getOrderInfo(orderId);
             return R.data(orderInfo);
         } catch (Exception e) {
             log.error("查询订单信息失败: {}", e.getMessage(), e);
@@ -390,7 +388,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "查询订单变更记录", notes = "根据订单ID查询订单的所有变更记录(按批次分组),用于展示每次下单/加餐都加了什么商品")
     @GetMapping("/change-log/{orderId}")
-    public R<List<WechatOrderChangeLogBatchVO>> getOrderChangeLogs(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
+    public R<List<OrderChangeLogBatchVO>> getOrderChangeLogs(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         log.info("StoreOrderController.getOrderChangeLogs?orderId={}", orderId);
         try {
             // 从 token 获取用户信息
@@ -398,7 +396,7 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            List<WechatOrderChangeLogBatchVO> changeLogs = orderService.getOrderChangeLogs(orderId);
+            List<OrderChangeLogBatchVO> changeLogs = orderService.getOrderChangeLogs(orderId);
             return R.data(changeLogs);
         } catch (Exception e) {
             log.error("查询订单变更记录失败: {}", e.getMessage(), e);
@@ -409,7 +407,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单列表,包含订单中的菜品数量、菜品名称、菜品图片。支持按订单编号或菜品名称搜索(限15字)")
     @GetMapping("/page")
-    public R<IPage<WechatStoreOrderPageVO>> getOrderPage(
+    public R<IPage<StoreOrderPageVO>> getOrderPage(
             @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
             @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
             @ApiParam(value = "门店ID") @RequestParam(required = false) Integer storeId,
@@ -423,8 +421,8 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            Page<WechatStoreOrder> page = new Page<>(current, size);
-            IPage<WechatStoreOrderPageVO> result = orderService.getOrderPageWithCuisines(page, storeId, tableId, orderStatus, keyword);
+            Page<StoreOrder> page = new Page<>(current, size);
+            IPage<StoreOrderPageVO> result = orderService.getOrderPageWithCuisines(page, storeId, tableId, orderStatus, keyword);
             return R.data(result);
         } catch (Exception e) {
             log.error("分页查询订单列表失败: {}", e.getMessage(), e);
@@ -434,7 +432,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "查询我的订单", notes = "通过标识查询我的未支付订单或历史订单,包含订单中的菜品数量、菜品名称、菜品图片。type: 0或unpaid-未支付订单, 1或history-历史订单")
     @GetMapping("/my-orders")
-    public R<IPage<WechatStoreOrderPageVO>> getMyOrders(
+    public R<IPage<StoreOrderPageVO>> getMyOrders(
             @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
             @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
             @ApiParam(value = "订单类型(0或unpaid:未支付订单, 1或history:历史订单)", required = true) @RequestParam String type) {
@@ -445,8 +443,8 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            Page<WechatStoreOrder> page = new Page<>(current, size);
-            IPage<WechatStoreOrderPageVO> result = orderService.getMyOrdersWithCuisines(page, type);
+            Page<StoreOrder> page = new Page<>(current, size);
+            IPage<StoreOrderPageVO> result = orderService.getMyOrdersWithCuisines(page, type);
             return R.data(result);
         } catch (Exception e) {
             log.error("查询我的订单失败: {}", e.getMessage(), e);
@@ -456,7 +454,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "换桌", notes = "换桌并迁移购物车、未完成的订单以及其他关联表数据")
     @PostMapping("/change-table")
-    public R<WechatCartDTO> changeTable(@Valid @RequestBody WechatChangeTableDTO dto) {
+    public R<CartDTO> changeTable(@Valid @RequestBody ChangeTableDTO dto) {
         log.info("StoreOrderController.changeTable?dto={}", dto);
         try {
             // 从 token 获取用户信息
@@ -466,7 +464,7 @@ public class StoreOrderController {
             }
 
             // 调用Service层处理换桌业务逻辑
-            WechatCartDTO cart = orderService.changeTable(dto.getFromTableId(), dto.getToTableId(), dto.getChangeReason(), userId);
+            CartDTO cart = orderService.changeTable(dto.getFromTableId(), dto.getToTableId(), dto.getChangeReason(), userId);
 
             return R.data(cart);
         } catch (Exception e) {
@@ -525,7 +523,7 @@ public class StoreOrderController {
 
     @ApiOperation(value = "更新订单优惠券", notes = "重新选择优惠券")
     @PostMapping("/update-coupon")
-    public R<WechatStoreOrder> updateOrderCoupon(@Valid @RequestBody WechatUpdateOrderCouponDTO dto) {
+    public R<StoreOrder> updateOrderCoupon(@Valid @RequestBody shop.alien.entity.store.dto.UpdateOrderCouponDTO dto) {
         log.info("StoreOrderController.updateOrderCoupon?dto={}", dto);
         try {
             // 从 token 获取用户信息
@@ -533,7 +531,7 @@ public class StoreOrderController {
             if (userId == null) {
                 return R.fail("用户未登录");
             }
-            WechatStoreOrder order = orderService.updateOrderCoupon(dto.getOrderId(), dto.getCouponId());
+            StoreOrder order = orderService.updateOrderCoupon(dto.getOrderId(), dto.getCouponId());
             return R.data(order);
         } catch (Exception e) {
             log.error("更新订单优惠券失败: {}", e.getMessage(), e);
@@ -554,14 +552,14 @@ public class StoreOrderController {
             boolean result = orderService.resetTable(tableId);
             if (result) {
                 // 推送购物车更新消息(清空购物车)
-                WechatCartDTO emptyCart = new WechatCartDTO();
+                CartDTO emptyCart = new CartDTO();
                 emptyCart.setTableId(tableId);
                 emptyCart.setItems(java.util.Collections.emptyList());
                 emptyCart.setTotalAmount(java.math.BigDecimal.ZERO);
                 emptyCart.setTotalQuantity(0);
                 
                 // 查询桌号信息
-                WechatStoreTable table = storeTableMapper.selectById(tableId);
+                StoreTable table = storeTableMapper.selectById(tableId);
                 if (table != null) {
                     emptyCart.setTableNumber(table.getTableNumber());
                     emptyCart.setStoreId(table.getStoreId());

+ 11 - 11
alien-dining/src/main/java/shop/alien/dining/service/CartService.java

@@ -1,7 +1,7 @@
 package shop.alien.dining.service;
 
-import shop.alien.entity.store.dto.wechat.WechatAddCartItemDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
+import shop.alien.entity.store.dto.AddCartItemDTO;
+import shop.alien.entity.store.dto.CartDTO;
 
 /**
  * 购物车服务接口
@@ -17,7 +17,7 @@ public interface CartService {
      * @param tableId 桌号ID
      * @return 购物车信息
      */
-    WechatCartDTO getCart(Integer tableId);
+    CartDTO getCart(Integer tableId);
 
     /**
      * 添加商品到购物车
@@ -25,7 +25,7 @@ public interface CartService {
      * @param dto 添加购物车商品DTO
      * @return 购物车信息
      */
-    WechatCartDTO addItem(WechatAddCartItemDTO dto);
+    CartDTO addItem(AddCartItemDTO dto);
 
     /**
      * 更新购物车商品数量
@@ -35,7 +35,7 @@ public interface CartService {
      * @param quantity  数量
      * @return 购物车信息
      */
-    WechatCartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity);
+    CartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity);
 
     /**
      * 删除购物车商品
@@ -44,7 +44,7 @@ public interface CartService {
      * @param cuisineId 菜品ID
      * @return 购物车信息
      */
-    WechatCartDTO removeItem(Integer tableId, Integer cuisineId);
+    CartDTO removeItem(Integer tableId, Integer cuisineId);
 
     /**
      * 清空购物车
@@ -60,7 +60,7 @@ public interface CartService {
      * @param toTableId   目标桌号ID
      * @return 迁移后的购物车信息
      */
-    WechatCartDTO migrateCart(Integer fromTableId, Integer toTableId);
+    CartDTO migrateCart(Integer fromTableId, Integer toTableId);
 
     /**
      * 检查桌号是否已使用优惠券
@@ -92,7 +92,7 @@ public interface CartService {
      * @param dinerCount 用餐人数
      * @return 购物车信息
      */
-    WechatCartDTO setDinerCount(Integer tableId, Integer dinerCount);
+    CartDTO setDinerCount(Integer tableId, Integer dinerCount);
 
     /**
      * 更新餐具数量
@@ -101,7 +101,7 @@ public interface CartService {
      * @param quantity 餐具数量
      * @return 购物车信息
      */
-    WechatCartDTO updateTablewareQuantity(Integer tableId, Integer quantity);
+    CartDTO updateTablewareQuantity(Integer tableId, Integer quantity);
 
     /**
      * 锁定购物车商品数量(下单时调用,将当前数量锁定,不允许减少或删除)
@@ -109,7 +109,7 @@ public interface CartService {
      * @param tableId 桌号ID
      * @return 购物车信息
      */
-    WechatCartDTO lockCartItems(Integer tableId);
+    CartDTO lockCartItems(Integer tableId);
 
     /**
      * 解锁购物车商品数量(取消订单时调用,清除已下单数量,允许重新下单)
@@ -117,5 +117,5 @@ public interface CartService {
      * @param tableId 桌号ID
      * @return 购物车信息
      */
-    WechatCartDTO unlockCartItems(Integer tableId);
+    CartDTO unlockCartItems(Integer tableId);
 }

+ 2 - 2
alien-dining/src/main/java/shop/alien/dining/service/DiningService.java

@@ -87,7 +87,7 @@ public interface DiningService {
      * @param userId 用户ID
      * @return 订单确认页面信息
      */
-    shop.alien.entity.store.vo.wechat.WechatOrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId);
+    OrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId);
 
     /**
      * 锁定订单(防止多人同时下单)
@@ -121,7 +121,7 @@ public interface DiningService {
      * @param userId 用户ID
      * @return 订单结算确认页面信息
      */
-    shop.alien.entity.store.vo.wechat.WechatOrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId);
+    shop.alien.entity.store.vo.OrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId);
 
     /**
      * 锁定订单结算(防止多人同时结算)

+ 10 - 10
alien-dining/src/main/java/shop/alien/dining/service/StoreInfoService.java

@@ -1,10 +1,10 @@
 package shop.alien.dining.service;
 
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCategory;
-import shop.alien.entity.store.wechat.WechatStoreTable;
-import shop.alien.entity.store.dto.wechat.WechatStoreInfoWithHomepageCuisinesDTO;
-import shop.alien.entity.store.vo.wechat.WechatCategoryWithCuisinesVO;
+import shop.alien.entity.store.StoreCuisine;
+import shop.alien.entity.store.StoreCuisineCategory;
+import shop.alien.entity.store.StoreTable;
+import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
 
 import java.util.List;
 
@@ -22,7 +22,7 @@ public interface StoreInfoService {
      * @param storeId 门店ID
      * @return 桌号列表
      */
-    List<WechatStoreTable> getTablesByStoreId(Integer storeId);
+    List<StoreTable> getTablesByStoreId(Integer storeId);
 
     /**
      * 根据门店ID查询菜品种类列表
@@ -30,7 +30,7 @@ public interface StoreInfoService {
      * @param storeId 门店ID
      * @return 菜品种类列表
      */
-    List<WechatStoreCuisineCategory> getCategoriesByStoreId(Integer storeId);
+    List<StoreCuisineCategory> getCategoriesByStoreId(Integer storeId);
 
     /**
      * 根据菜品种类ID查询菜品信息列表
@@ -38,7 +38,7 @@ public interface StoreInfoService {
      * @param categoryId 菜品种类ID
      * @return 菜品信息列表
      */
-    List<WechatStoreCuisine> getCuisinesByCategoryId(Integer categoryId);
+    List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId);
 
     /**
      * 根据门店ID查询菜品种类及每个分类下的菜品列表(一次返回种类+菜品)
@@ -47,7 +47,7 @@ public interface StoreInfoService {
      * @param keyword 菜品名称模糊查询关键词(可选,为空则不按名称筛选)
      * @return 菜品种类及下属菜品列表
      */
-    List<WechatCategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword);
+    List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword);
 
     /**
      * 删除菜品种类:仅逻辑删除分类并解除菜品与该分类的绑定关系,价目表(菜品)本身不改动
@@ -63,5 +63,5 @@ public interface StoreInfoService {
      * @param storeId 商铺ID
      * @return 店铺信息和首页展示美食价目表信息
      */
-    WechatStoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId);
+    StoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId);
 }

+ 19 - 21
alien-dining/src/main/java/shop/alien/dining/service/StoreOrderService.java

@@ -3,13 +3,11 @@ package shop.alien.dining.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
-import shop.alien.entity.store.wechat.WechatStoreOrder;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
-import shop.alien.entity.store.dto.wechat.WechatCreateOrderDTO;
-import shop.alien.entity.store.vo.wechat.WechatOrderChangeLogBatchVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderInfoVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderDetailWithChangeLogVO;
-import shop.alien.entity.store.vo.wechat.WechatStoreOrderPageVO;
+import shop.alien.entity.store.StoreOrder;
+import shop.alien.entity.store.dto.CreateOrderDTO;
+import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
+import shop.alien.entity.store.vo.OrderInfoVO;
+import shop.alien.entity.store.vo.StoreOrderPageVO;
 
 import java.util.List;
 
@@ -19,7 +17,7 @@ import java.util.List;
  * @author system
  * @since 2025-01-XX
  */
-public interface StoreOrderService extends IService<WechatStoreOrder> {
+public interface StoreOrderService extends IService<StoreOrder> {
 
     /**
      * 创建订单
@@ -27,7 +25,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param dto 创建订单DTO
      * @return 订单信息
      */
-    WechatStoreOrder createOrder(WechatCreateOrderDTO dto);
+    StoreOrder createOrder(CreateOrderDTO dto);
 
     /**
      * 支付订单
@@ -36,7 +34,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param payType 支付方式
      * @return 订单信息
      */
-    WechatStoreOrder payOrder(Integer orderId, Integer payType);
+    StoreOrder payOrder(Integer orderId, Integer payType);
 
     /**
      * 取消订单
@@ -52,7 +50,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param orderNo 订单号
      * @return 订单信息
      */
-    WechatStoreOrder getOrderByOrderNo(String orderNo);
+    StoreOrder getOrderByOrderNo(String orderNo);
 
     /**
      * 根据ID查询订单
@@ -60,7 +58,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param orderId 订单ID
      * @return 订单信息
      */
-    WechatStoreOrder getOrderById(Integer orderId);
+    StoreOrder getOrderById(Integer orderId);
 
     /**
      * 分页查询订单列表
@@ -72,7 +70,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param keyword  搜索关键词(订单编号或菜品名称,限15字)
      * @return 订单分页列表
      */
-    IPage<WechatStoreOrder> getOrderPage(Page<WechatStoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
+    IPage<StoreOrder> getOrderPage(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
 
     /**
      * 分页查询订单列表(包含菜品信息)
@@ -84,7 +82,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param keyword  搜索关键词(订单编号或菜品名称,限15字)
      * @return 订单分页列表(包含菜品信息)
      */
-    IPage<WechatStoreOrderPageVO> getOrderPageWithCuisines(Page<WechatStoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
+    IPage<StoreOrderPageVO> getOrderPageWithCuisines(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
 
     /**
      * 完成订单(支付完成后调用)
@@ -109,7 +107,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param couponId 优惠券ID(可为空,表示不使用优惠券)
      * @return 订单信息
      */
-    WechatStoreOrder updateOrderCoupon(Integer orderId, Integer couponId);
+    StoreOrder updateOrderCoupon(Integer orderId, Integer couponId);
 
     /**
      * 管理员重置餐桌(删除购物车数据、未支付/已取消的订单数据,并重置餐桌表)
@@ -126,7 +124,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param orderId 订单ID
      * @return 订单信息
      */
-    WechatOrderInfoVO getOrderInfo(Integer orderId);
+    OrderInfoVO getOrderInfo(Integer orderId);
 
     /**
      * 查询订单的所有变更记录(按批次分组)
@@ -134,7 +132,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param orderId 订单ID
      * @return 变更记录批次列表
      */
-    List<WechatOrderChangeLogBatchVO> getOrderChangeLogs(Integer orderId);
+    List<OrderChangeLogBatchVO> getOrderChangeLogs(Integer orderId);
 
     /**
      * 查询订单详情(包含订单基本信息和按批次分组的变更记录)
@@ -142,7 +140,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param orderId 订单ID
      * @return 订单详情(包含变更记录)
      */
-    WechatOrderDetailWithChangeLogVO getOrderDetailWithChangeLog(Integer orderId);
+    shop.alien.entity.store.vo.OrderDetailWithChangeLogVO getOrderDetailWithChangeLog(Integer orderId);
 
     /**
      * 支付完成后重置餐桌(保留订单数据,只重置餐桌绑定关系)
@@ -158,7 +156,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param type 订单类型(0或"unpaid":未支付订单, 1或"history":历史订单)
      * @return 订单分页列表
      */
-    IPage<WechatStoreOrder> getMyOrders(Page<WechatStoreOrder> page, String type);
+    IPage<StoreOrder> getMyOrders(Page<StoreOrder> page, String type);
 
     /**
      * 查询我的订单(包含菜品信息)
@@ -167,7 +165,7 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param type 订单类型(0或"unpaid":未支付订单, 1或"history":历史订单)
      * @return 订单分页列表(包含菜品信息)
      */
-    IPage<WechatStoreOrderPageVO> getMyOrdersWithCuisines(Page<WechatStoreOrder> page, String type);
+    IPage<StoreOrderPageVO> getMyOrdersWithCuisines(Page<StoreOrder> page, String type);
 
     /**
      * 换桌时迁移所有关联数据(订单、订单变更记录、优惠券使用记录等)
@@ -187,5 +185,5 @@ public interface StoreOrderService extends IService<WechatStoreOrder> {
      * @param userId       操作用户ID
      * @return 迁移后的购物车信息
      */
-    WechatCartDTO changeTable(Integer fromTableId, Integer toTableId, String changeReason, Integer userId);
+    shop.alien.entity.store.dto.CartDTO changeTable(Integer fromTableId, Integer toTableId, String changeReason, Integer userId);
 }

+ 147 - 147
alien-dining/src/main/java/shop/alien/dining/service/impl/CartServiceImpl.java

@@ -9,19 +9,19 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 import shop.alien.dining.config.BaseRedisService;
 import shop.alien.dining.service.CartService;
-import shop.alien.entity.store.wechat.WechatStoreCart;
-import shop.alien.entity.store.wechat.WechatStoreCouponUsage;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
+import shop.alien.entity.store.StoreCart;
+import shop.alien.entity.store.StoreCouponUsage;
+import shop.alien.entity.store.StoreCuisine;
 import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.wechat.WechatStoreTable;
-import shop.alien.entity.store.dto.wechat.WechatAddCartItemDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartItemDTO;
-import shop.alien.mapper.wechat.WechatStoreCartMapper;
-import shop.alien.mapper.wechat.WechatStoreCouponUsageMapper;
-import shop.alien.mapper.wechat.WechatStoreCuisineMapper;
+import shop.alien.entity.store.StoreTable;
+import shop.alien.entity.store.dto.AddCartItemDTO;
+import shop.alien.entity.store.dto.CartDTO;
+import shop.alien.entity.store.dto.CartItemDTO;
+import shop.alien.mapper.StoreCartMapper;
+import shop.alien.mapper.StoreCouponUsageMapper;
+import shop.alien.mapper.StoreCuisineMapper;
 import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.wechat.WechatStoreTableMapper;
+import shop.alien.mapper.StoreTableMapper;
 import shop.alien.dining.util.TokenUtil;
 
 import java.math.BigDecimal;
@@ -44,8 +44,8 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public class CartServiceImpl implements CartService {
 
-    private static final String CART_KEY_PREFIX = "wechat:cart:table:";
-    private static final String COUPON_USED_KEY_PREFIX = "wechat:coupon:used:table:";
+    private static final String CART_KEY_PREFIX = "cart:table:";
+    private static final String COUPON_USED_KEY_PREFIX = "coupon:used:table:";
     private static final int CART_EXPIRE_SECONDS = 24 * 60 * 60; // 24小时过期
 
     // 异步写入数据库的线程池(专门用于购物车数据库写入)
@@ -56,23 +56,23 @@ public class CartServiceImpl implements CartService {
     });
 
     private final BaseRedisService baseRedisService;
-    private final WechatStoreTableMapper storeTableMapper;
-    private final WechatStoreCuisineMapper storeCuisineMapper;
-    private final WechatStoreCartMapper storeCartMapper;
-    private final WechatStoreCouponUsageMapper storeCouponUsageMapper;
+    private final StoreTableMapper storeTableMapper;
+    private final StoreCuisineMapper storeCuisineMapper;
+    private final StoreCartMapper storeCartMapper;
+    private final StoreCouponUsageMapper storeCouponUsageMapper;
     private final StoreInfoMapper storeInfoMapper;
 
     @Override
-    public WechatCartDTO getCart(Integer tableId) {
+    public CartDTO getCart(Integer tableId) {
         log.info("获取购物车, tableId={}", tableId);
         String cartKey = CART_KEY_PREFIX + tableId;
         String cartJson = baseRedisService.getString(cartKey);
 
-        WechatCartDTO cart = new WechatCartDTO();
+        CartDTO cart = new CartDTO();
         cart.setTableId(tableId);
 
         // 查询桌号信息
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table != null) {
             cart.setTableNumber(table.getTableNumber());
             cart.setStoreId(table.getStoreId());
@@ -81,15 +81,15 @@ public class CartServiceImpl implements CartService {
         if (StringUtils.hasText(cartJson)) {
             try {
                 JSONObject cartObj = JSON.parseObject(cartJson);
-                List<WechatCartItemDTO> items = cartObj.getList("items", WechatCartItemDTO.class);
+                List<CartItemDTO> items = cartObj.getList("items", CartItemDTO.class);
                 if (items != null) {
                     cart.setItems(items);
                     // 计算总金额和总数量
                     BigDecimal totalAmount = items.stream()
-                            .map(WechatCartItemDTO::getSubtotalAmount)
+                            .map(CartItemDTO::getSubtotalAmount)
                             .reduce(BigDecimal.ZERO, BigDecimal::add);
                     Integer totalQuantity = items.stream()
-                            .mapToInt(WechatCartItemDTO::getQuantity)
+                            .mapToInt(CartItemDTO::getQuantity)
                             .sum();
                     cart.setTotalAmount(totalAmount);
                     cart.setTotalQuantity(totalQuantity);
@@ -115,30 +115,30 @@ public class CartServiceImpl implements CartService {
     /**
      * 从数据库加载购物车
      */
-    private WechatCartDTO loadCartFromDatabase(Integer tableId) {
+    private CartDTO loadCartFromDatabase(Integer tableId) {
         log.info("从数据库加载购物车, tableId={}", tableId);
-        WechatCartDTO cart = new WechatCartDTO();
+        CartDTO cart = new CartDTO();
         cart.setTableId(tableId);
         cart.setItems(new ArrayList<>());
         cart.setTotalAmount(BigDecimal.ZERO);
         cart.setTotalQuantity(0);
 
         // 查询桌号信息
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table != null) {
             cart.setTableNumber(table.getTableNumber());
             cart.setStoreId(table.getStoreId());
         }
 
         // 从数据库查询购物车数据
-        LambdaQueryWrapper<WechatStoreCart> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCart::getTableId, tableId);
-        wrapper.eq(WechatStoreCart::getDeleteFlag, 0);
-        List<WechatStoreCart> cartList = storeCartMapper.selectList(wrapper);
+        LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCart::getTableId, tableId);
+        wrapper.eq(StoreCart::getDeleteFlag, 0);
+        List<StoreCart> cartList = storeCartMapper.selectList(wrapper);
 
         if (cartList != null && !cartList.isEmpty()) {
-            List<WechatCartItemDTO> items = cartList.stream().map(cartItem -> {
-                WechatCartItemDTO item = new WechatCartItemDTO();
+            List<CartItemDTO> items = cartList.stream().map(cartItem -> {
+                CartItemDTO item = new CartItemDTO();
                 item.setCuisineId(cartItem.getCuisineId());
                 item.setCuisineName(cartItem.getCuisineName());
                 item.setCuisineImage(cartItem.getCuisineImage());
@@ -154,10 +154,10 @@ public class CartServiceImpl implements CartService {
 
             cart.setItems(items);
             BigDecimal totalAmount = items.stream()
-                    .map(WechatCartItemDTO::getSubtotalAmount)
+                    .map(CartItemDTO::getSubtotalAmount)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
             Integer totalQuantity = items.stream()
-                    .mapToInt(WechatCartItemDTO::getQuantity)
+                    .mapToInt(CartItemDTO::getQuantity)
                     .sum();
             cart.setTotalAmount(totalAmount);
             cart.setTotalQuantity(totalQuantity);
@@ -170,16 +170,16 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO addItem(WechatAddCartItemDTO dto) {
+    public CartDTO addItem(AddCartItemDTO dto) {
         log.info("添加商品到购物车, dto={}", dto);
         // 验证桌号
-        WechatStoreTable table = storeTableMapper.selectById(dto.getTableId());
+        StoreTable table = storeTableMapper.selectById(dto.getTableId());
         if (table == null) {
             throw new RuntimeException("桌号不存在");
         }
 
         // 验证菜品
-        WechatStoreCuisine cuisine = storeCuisineMapper.selectById(dto.getCuisineId());
+        StoreCuisine cuisine = storeCuisineMapper.selectById(dto.getCuisineId());
         if (cuisine == null) {
             throw new RuntimeException("菜品不存在");
         }
@@ -192,11 +192,11 @@ public class CartServiceImpl implements CartService {
         String userPhone = TokenUtil.getCurrentUserPhone();
 
         // 获取购物车
-        WechatCartDTO cart = getCart(dto.getTableId());
+        CartDTO cart = getCart(dto.getTableId());
 
         // 查找是否已存在该商品
-        List<WechatCartItemDTO> items = cart.getItems();
-        WechatCartItemDTO existingItem = items.stream()
+        List<CartItemDTO> items = cart.getItems();
+        CartItemDTO existingItem = items.stream()
                 .filter(item -> item.getCuisineId().equals(dto.getCuisineId()))
                 .findFirst()
                 .orElse(null);
@@ -220,7 +220,7 @@ public class CartServiceImpl implements CartService {
             }
         } else {
             // 添加新商品
-            WechatCartItemDTO newItem = new WechatCartItemDTO();
+            CartItemDTO newItem = new CartItemDTO();
             newItem.setCuisineId(cuisine.getId());
             newItem.setCuisineName(cuisine.getName());
             newItem.setCuisineType(cuisine.getCuisineType());
@@ -237,10 +237,10 @@ public class CartServiceImpl implements CartService {
 
         // 重新计算总金额和总数量
         BigDecimal totalAmount = items.stream()
-                .map(WechatCartItemDTO::getSubtotalAmount)
+                .map(CartItemDTO::getSubtotalAmount)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         Integer totalQuantity = items.stream()
-                .mapToInt(WechatCartItemDTO::getQuantity)
+                .mapToInt(CartItemDTO::getQuantity)
                 .sum();
         cart.setTotalAmount(totalAmount);
         cart.setTotalQuantity(totalQuantity);
@@ -252,7 +252,7 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity) {
+    public CartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity) {
         log.info("更新购物车商品数量, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
         
         // 如果数量为0或小于0,删除该商品
@@ -261,9 +261,9 @@ public class CartServiceImpl implements CartService {
             return removeItem(tableId, cuisineId);
         }
 
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
-        WechatCartItemDTO item = items.stream()
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
+        CartItemDTO item = items.stream()
                 .filter(i -> i.getCuisineId().equals(cuisineId))
                 .findFirst()
                 .orElse(null);
@@ -284,10 +284,10 @@ public class CartServiceImpl implements CartService {
 
             // 重新计算总金额和总数量
             BigDecimal totalAmount = items.stream()
-                    .map(WechatCartItemDTO::getSubtotalAmount)
+                    .map(CartItemDTO::getSubtotalAmount)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
             Integer totalQuantity = items.stream()
-                    .mapToInt(WechatCartItemDTO::getQuantity)
+                    .mapToInt(CartItemDTO::getQuantity)
                     .sum();
             cart.setTotalAmount(totalAmount);
             cart.setTotalQuantity(totalQuantity);
@@ -298,7 +298,7 @@ public class CartServiceImpl implements CartService {
             log.info("商品不在购物车中,自动添加, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
             
             // 验证菜品
-            WechatStoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
+            StoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
             if (cuisine == null) {
                 throw new RuntimeException("菜品不存在");
             }
@@ -311,7 +311,7 @@ public class CartServiceImpl implements CartService {
             String userPhone = TokenUtil.getCurrentUserPhone();
 
             // 创建新的购物车商品项
-            WechatCartItemDTO newItem = new WechatCartItemDTO();
+            CartItemDTO newItem = new CartItemDTO();
             newItem.setCuisineId(cuisine.getId());
             newItem.setCuisineName(cuisine.getName());
             newItem.setCuisineType(cuisine.getCuisineType());
@@ -326,10 +326,10 @@ public class CartServiceImpl implements CartService {
 
             // 重新计算总金额和总数量
             BigDecimal totalAmount = items.stream()
-                    .map(WechatCartItemDTO::getSubtotalAmount)
+                    .map(CartItemDTO::getSubtotalAmount)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
             Integer totalQuantity = items.stream()
-                    .mapToInt(WechatCartItemDTO::getQuantity)
+                    .mapToInt(CartItemDTO::getQuantity)
                     .sum();
             cart.setTotalAmount(totalAmount);
             cart.setTotalQuantity(totalQuantity);
@@ -343,13 +343,13 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO removeItem(Integer tableId, Integer cuisineId) {
+    public CartDTO removeItem(Integer tableId, Integer cuisineId) {
         log.info("删除购物车商品, tableId={}, cuisineId={}", tableId, cuisineId);
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
         
         // 检查是否有已下单数量,如果有则不允许删除
-        WechatCartItemDTO item = items.stream()
+        CartItemDTO item = items.stream()
                 .filter(i -> i.getCuisineId().equals(cuisineId))
                 .findFirst()
                 .orElse(null);
@@ -365,10 +365,10 @@ public class CartServiceImpl implements CartService {
 
         // 重新计算总金额和总数量
         BigDecimal totalAmount = items.stream()
-                .map(WechatCartItemDTO::getSubtotalAmount)
+                .map(CartItemDTO::getSubtotalAmount)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         Integer totalQuantity = items.stream()
-                .mapToInt(WechatCartItemDTO::getQuantity)
+                .mapToInt(CartItemDTO::getQuantity)
                 .sum();
         cart.setTotalAmount(totalAmount);
         cart.setTotalQuantity(totalQuantity);
@@ -382,8 +382,8 @@ public class CartServiceImpl implements CartService {
         log.info("清空购物车(保留已下单商品), tableId={}", tableId);
         
         // 获取购物车
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
         
         if (items == null || items.isEmpty()) {
             log.info("购物车为空,无需清空, tableId={}", tableId);
@@ -391,13 +391,13 @@ public class CartServiceImpl implements CartService {
         }
         
         // 分离已下单的商品、未下单的商品和餐具
-        List<WechatCartItemDTO> orderedItems = new ArrayList<>(); // 已下单的商品(保留,数量恢复为已下单数量)
+        List<CartItemDTO> orderedItems = new ArrayList<>(); // 已下单的商品(保留,数量恢复为已下单数量)
         List<Integer> orderedCuisineIds = new ArrayList<>(); // 已下单的商品ID列表
-        List<WechatCartItemDTO> unorderedItems = new ArrayList<>(); // 未下单的商品(删除)
-        WechatCartItemDTO tablewareItem = null; // 餐具项(始终保留)
+        List<CartItemDTO> unorderedItems = new ArrayList<>(); // 未下单的商品(删除)
+        CartItemDTO tablewareItem = null; // 餐具项(始终保留)
         boolean hasChanges = false; // 是否有变化(需要更新)
         
-        for (WechatCartItemDTO item : items) {
+        for (CartItemDTO item : items) {
             // 餐具始终保留,不清空
             if (TABLEWARE_CUISINE_ID.equals(item.getCuisineId())) {
                 tablewareItem = item;
@@ -449,10 +449,10 @@ public class CartServiceImpl implements CartService {
             cart.setItems(orderedItems);
             // 重新计算总金额和总数量(只计算保留的商品,数量已恢复为已下单数量)
             BigDecimal totalAmount = orderedItems.stream()
-                    .map(WechatCartItemDTO::getSubtotalAmount)
+                    .map(CartItemDTO::getSubtotalAmount)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
             Integer totalQuantity = orderedItems.stream()
-                    .mapToInt(WechatCartItemDTO::getQuantity)
+                    .mapToInt(CartItemDTO::getQuantity)
                     .sum();
             cart.setTotalAmount(totalAmount);
             cart.setTotalQuantity(totalQuantity);
@@ -469,19 +469,19 @@ public class CartServiceImpl implements CartService {
             
             // 2. 从数据库中逻辑删除未下单的商品(排除餐具)
             if (!unorderedItems.isEmpty()) {
-                LambdaQueryWrapper<WechatStoreCart> wrapper = new LambdaQueryWrapper<>();
-                wrapper.eq(WechatStoreCart::getTableId, tableId);
-                wrapper.eq(WechatStoreCart::getDeleteFlag, 0);
+                LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
+                wrapper.eq(StoreCart::getTableId, tableId);
+                wrapper.eq(StoreCart::getDeleteFlag, 0);
                 // 排除餐具(cuisineId = -1)
-                wrapper.ne(WechatStoreCart::getCuisineId, TABLEWARE_CUISINE_ID);
+                wrapper.ne(StoreCart::getCuisineId, TABLEWARE_CUISINE_ID);
                 if (!orderedCuisineIds.isEmpty()) {
                     // 排除已下单的商品ID(包括餐具)
-                    wrapper.notIn(WechatStoreCart::getCuisineId, orderedCuisineIds);
+                    wrapper.notIn(StoreCart::getCuisineId, orderedCuisineIds);
                 }
-                List<WechatStoreCart> cartListToDelete = storeCartMapper.selectList(wrapper);
+                List<StoreCart> cartListToDelete = storeCartMapper.selectList(wrapper);
                 if (cartListToDelete != null && !cartListToDelete.isEmpty()) {
                     List<Integer> cartIds = cartListToDelete.stream()
-                            .map(WechatStoreCart::getId)
+                            .map(StoreCart::getId)
                             .collect(Collectors.toList());
                     // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
                     storeCartMapper.deleteBatchIds(cartIds);
@@ -496,7 +496,7 @@ public class CartServiceImpl implements CartService {
             }
             
             // 4. 更新桌号表的购物车统计
-            WechatStoreTable table = storeTableMapper.selectById(tableId);
+            StoreTable table = storeTableMapper.selectById(tableId);
             if (table != null) {
                 table.setCartItemCount(totalQuantity);
                 table.setCartTotalAmount(totalAmount);
@@ -511,24 +511,24 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO migrateCart(Integer fromTableId, Integer toTableId) {
+    public CartDTO migrateCart(Integer fromTableId, Integer toTableId) {
         log.info("迁移购物车, fromTableId={}, toTableId={}", fromTableId, toTableId);
         // 获取原购物车
-        WechatCartDTO fromCart = getCart(fromTableId);
+        CartDTO fromCart = getCart(fromTableId);
 
         // 验证目标桌号
-        WechatStoreTable toTable = storeTableMapper.selectById(toTableId);
+        StoreTable toTable = storeTableMapper.selectById(toTableId);
         if (toTable == null) {
             throw new RuntimeException("目标桌号不存在");
         }
 
         // 获取目标购物车
-        WechatCartDTO toCart = getCart(toTableId);
+        CartDTO toCart = getCart(toTableId);
 
         // 合并购物车(如果目标桌号已有商品,则合并)
-        List<WechatCartItemDTO> mergedItems = new ArrayList<>(toCart.getItems());
-        for (WechatCartItemDTO fromItem : fromCart.getItems()) {
-            WechatCartItemDTO existingItem = mergedItems.stream()
+        List<CartItemDTO> mergedItems = new ArrayList<>(toCart.getItems());
+        for (CartItemDTO fromItem : fromCart.getItems()) {
+            CartItemDTO existingItem = mergedItems.stream()
                     .filter(item -> item.getCuisineId().equals(fromItem.getCuisineId()))
                     .findFirst()
                     .orElse(null);
@@ -556,10 +556,10 @@ public class CartServiceImpl implements CartService {
 
         // 重新计算总金额和总数量
         BigDecimal totalAmount = mergedItems.stream()
-                .map(WechatCartItemDTO::getSubtotalAmount)
+                .map(CartItemDTO::getSubtotalAmount)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         Integer totalQuantity = mergedItems.stream()
-                .mapToInt(WechatCartItemDTO::getQuantity)
+                .mapToInt(CartItemDTO::getQuantity)
                 .sum();
         toCart.setTotalAmount(totalAmount);
         toCart.setTotalQuantity(totalQuantity);
@@ -593,13 +593,13 @@ public class CartServiceImpl implements CartService {
         }
 
         // Redis中没有,查数据库
-        LambdaQueryWrapper<WechatStoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCouponUsage::getTableId, tableId);
-        wrapper.eq(WechatStoreCouponUsage::getDeleteFlag, 0);
-        wrapper.in(WechatStoreCouponUsage::getUsageStatus, 0, 1, 2); // 已标记使用、已下单、已支付
-        wrapper.orderByDesc(WechatStoreCouponUsage::getCreatedTime);
+        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCouponUsage::getTableId, tableId);
+        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
+        wrapper.in(StoreCouponUsage::getUsageStatus, 0, 1, 2); // 已标记使用、已下单、已支付
+        wrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
         wrapper.last("LIMIT 1");
-        WechatStoreCouponUsage usage = storeCouponUsageMapper.selectOne(wrapper);
+        StoreCouponUsage usage = storeCouponUsageMapper.selectOne(wrapper);
         return usage != null;
     }
 
@@ -610,22 +610,22 @@ public class CartServiceImpl implements CartService {
         baseRedisService.setString(couponUsedKey, String.valueOf(couponId), (long) CART_EXPIRE_SECONDS);
 
         // 保存到数据库
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table == null) {
             log.warn("桌号不存在, tableId={}", tableId);
             return;
         }
 
         // 检查是否已存在
-        LambdaQueryWrapper<WechatStoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCouponUsage::getTableId, tableId);
-        wrapper.eq(WechatStoreCouponUsage::getCouponId, couponId);
-        wrapper.eq(WechatStoreCouponUsage::getDeleteFlag, 0);
-        WechatStoreCouponUsage existing = storeCouponUsageMapper.selectOne(wrapper);
+        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCouponUsage::getTableId, tableId);
+        wrapper.eq(StoreCouponUsage::getCouponId, couponId);
+        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
+        StoreCouponUsage existing = storeCouponUsageMapper.selectOne(wrapper);
 
         if (existing == null) {
             Date now = new Date();
-            WechatStoreCouponUsage usage = new WechatStoreCouponUsage();
+            StoreCouponUsage usage = new StoreCouponUsage();
             usage.setTableId(tableId);
             usage.setStoreId(table.getStoreId());
             usage.setCouponId(couponId);
@@ -651,21 +651,21 @@ public class CartServiceImpl implements CartService {
         baseRedisService.delete(couponUsedKey);
 
         // 更新数据库(逻辑删除未下单的记录,使用 MyBatis-Plus 的 deleteBatchIds)
-        LambdaQueryWrapper<WechatStoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCouponUsage::getTableId, tableId);
-        wrapper.eq(WechatStoreCouponUsage::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCouponUsage::getUsageStatus, 0); // 只删除已标记使用但未下单的
-        List<WechatStoreCouponUsage> usageList = storeCouponUsageMapper.selectList(wrapper);
+        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCouponUsage::getTableId, tableId);
+        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
+        wrapper.eq(StoreCouponUsage::getUsageStatus, 0); // 只删除已标记使用但未下单的
+        List<StoreCouponUsage> usageList = storeCouponUsageMapper.selectList(wrapper);
         if (usageList != null && !usageList.isEmpty()) {
             List<Integer> usageIds = usageList.stream()
-                    .map(WechatStoreCouponUsage::getId)
+                    .map(StoreCouponUsage::getId)
                     .collect(Collectors.toList());
             // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
             storeCouponUsageMapper.deleteBatchIds(usageIds);
         }
 
         // 更新桌号表的优惠券ID
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table != null) {
             table.setCurrentCouponId(null);
             storeTableMapper.updateById(table);
@@ -703,7 +703,7 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO setDinerCount(Integer tableId, Integer dinerCount) {
+    public CartDTO setDinerCount(Integer tableId, Integer dinerCount) {
         log.info("设置用餐人数, tableId={}, dinerCount={}", tableId, dinerCount);
         
         if (dinerCount == null || dinerCount <= 0) {
@@ -711,14 +711,14 @@ public class CartServiceImpl implements CartService {
         }
 
         // 获取购物车
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
 
         // 获取门店ID和餐具单价
         Integer storeId = cart.getStoreId();
         if (storeId == null) {
             // 如果购物车中没有门店ID,从桌号获取
-            WechatStoreTable table = storeTableMapper.selectById(tableId);
+            StoreTable table = storeTableMapper.selectById(tableId);
             if (table != null) {
                 storeId = table.getStoreId();
             }
@@ -728,7 +728,7 @@ public class CartServiceImpl implements CartService {
         // 商铺未设置餐具费时,不往购物车加餐具;若已有餐具项则移除
         if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
             log.info("门店未设置餐具费, storeId={},设置就餐人数时不添加餐具", storeId);
-            WechatCartItemDTO existing = items.stream()
+            CartItemDTO existing = items.stream()
                     .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                     .findFirst()
                     .orElse(null);
@@ -737,7 +737,7 @@ public class CartServiceImpl implements CartService {
             }
         } else {
             // 查找是否已存在餐具项
-            WechatCartItemDTO tablewareItem = items.stream()
+            CartItemDTO tablewareItem = items.stream()
                     .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                     .findFirst()
                     .orElse(null);
@@ -754,7 +754,7 @@ public class CartServiceImpl implements CartService {
                 tablewareItem.setUnitPrice(tablewareUnitPrice);
                 tablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(dinerCount)));
             } else {
-                WechatCartItemDTO newTablewareItem = new WechatCartItemDTO();
+                CartItemDTO newTablewareItem = new CartItemDTO();
                 newTablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
                 newTablewareItem.setCuisineName(TABLEWARE_NAME);
                 newTablewareItem.setCuisineType(0);
@@ -770,10 +770,10 @@ public class CartServiceImpl implements CartService {
 
         // 重新计算总金额和总数量
         BigDecimal totalAmount = items.stream()
-                .map(WechatCartItemDTO::getSubtotalAmount)
+                .map(CartItemDTO::getSubtotalAmount)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         Integer totalQuantity = items.stream()
-                .mapToInt(WechatCartItemDTO::getQuantity)
+                .mapToInt(CartItemDTO::getQuantity)
                 .sum();
         cart.setTotalAmount(totalAmount);
         cart.setTotalQuantity(totalQuantity);
@@ -785,7 +785,7 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO updateTablewareQuantity(Integer tableId, Integer quantity) {
+    public CartDTO updateTablewareQuantity(Integer tableId, Integer quantity) {
         log.info("更新餐具数量, tableId={}, quantity={}", tableId, quantity);
         
         if (quantity == null || quantity < 0) {
@@ -798,13 +798,13 @@ public class CartServiceImpl implements CartService {
         }
 
         // 获取购物车
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
 
         // 获取门店ID和餐具单价
         Integer storeId = cart.getStoreId();
         if (storeId == null) {
-            WechatStoreTable table = storeTableMapper.selectById(tableId);
+            StoreTable table = storeTableMapper.selectById(tableId);
             if (table != null) {
                 storeId = table.getStoreId();
             }
@@ -814,17 +814,17 @@ public class CartServiceImpl implements CartService {
         // 商铺未设置餐具费(单价为0或未配置)时,不往购物车加餐具;若已有餐具项则移除
         if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
             log.info("门店未设置餐具费, storeId={},不添加餐具到购物车", storeId);
-            WechatCartItemDTO existing = items.stream()
+            CartItemDTO existing = items.stream()
                     .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                     .findFirst()
                     .orElse(null);
             if (existing != null) {
                 items.remove(existing);
                 BigDecimal totalAmount = items.stream()
-                        .map(WechatCartItemDTO::getSubtotalAmount)
+                        .map(CartItemDTO::getSubtotalAmount)
                         .reduce(BigDecimal.ZERO, BigDecimal::add);
                 Integer totalQuantity = items.stream()
-                        .mapToInt(WechatCartItemDTO::getQuantity)
+                        .mapToInt(CartItemDTO::getQuantity)
                         .sum();
                 cart.setTotalAmount(totalAmount);
                 cart.setTotalQuantity(totalQuantity);
@@ -834,7 +834,7 @@ public class CartServiceImpl implements CartService {
         }
 
         // 查找餐具项
-        WechatCartItemDTO tablewareItem = items.stream()
+        CartItemDTO tablewareItem = items.stream()
                 .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                 .findFirst()
                 .orElse(null);
@@ -844,7 +844,7 @@ public class CartServiceImpl implements CartService {
             Integer userId = TokenUtil.getCurrentUserId();
             String userPhone = TokenUtil.getCurrentUserPhone();
             
-            tablewareItem = new WechatCartItemDTO();
+            tablewareItem = new CartItemDTO();
             tablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
             tablewareItem.setCuisineName(TABLEWARE_NAME);
             tablewareItem.setCuisineType(0); // 0表示餐具
@@ -869,10 +869,10 @@ public class CartServiceImpl implements CartService {
 
         // 重新计算总金额和总数量
         BigDecimal totalAmount = items.stream()
-                .map(WechatCartItemDTO::getSubtotalAmount)
+                .map(CartItemDTO::getSubtotalAmount)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         Integer totalQuantity = items.stream()
-                .mapToInt(WechatCartItemDTO::getQuantity)
+                .mapToInt(CartItemDTO::getQuantity)
                 .sum();
         cart.setTotalAmount(totalAmount);
         cart.setTotalQuantity(totalQuantity);
@@ -884,12 +884,12 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO lockCartItems(Integer tableId) {
+    public CartDTO lockCartItems(Integer tableId) {
         log.info("锁定购物车商品数量(设置已下单数量), tableId={}", tableId);
         
         // 获取购物车
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
         
         if (items == null || items.isEmpty()) {
             log.warn("购物车为空,无需锁定, tableId={}", tableId);
@@ -898,7 +898,7 @@ public class CartServiceImpl implements CartService {
         
         // 遍历所有商品,将当前数量设置为已下单数量
         boolean hasChanges = false;
-        for (WechatCartItemDTO item : items) {
+        for (CartItemDTO item : items) {
             Integer currentQuantity = item.getQuantity();
             Integer lockedQuantity = item.getLockedQuantity();
             
@@ -928,12 +928,12 @@ public class CartServiceImpl implements CartService {
     }
 
     @Override
-    public WechatCartDTO unlockCartItems(Integer tableId) {
+    public CartDTO unlockCartItems(Integer tableId) {
         log.info("解锁购物车商品数量(清除已下单数量), tableId={}", tableId);
         
         // 获取购物车
-        WechatCartDTO cart = getCart(tableId);
-        List<WechatCartItemDTO> items = cart.getItems();
+        CartDTO cart = getCart(tableId);
+        List<CartItemDTO> items = cart.getItems();
         
         if (items == null || items.isEmpty()) {
             log.info("购物车为空,无需解锁, tableId={}", tableId);
@@ -942,7 +942,7 @@ public class CartServiceImpl implements CartService {
         
         // 遍历所有商品,清除已下单数量(lockedQuantity)
         boolean hasChanges = false;
-        for (WechatCartItemDTO item : items) {
+        for (CartItemDTO item : items) {
             if (item.getLockedQuantity() != null && item.getLockedQuantity() > 0) {
                 // 清除已下单数量,允许重新下单
                 item.setLockedQuantity(null);
@@ -966,7 +966,7 @@ public class CartServiceImpl implements CartService {
      * 保存购物车到Redis和数据库(优化后的双写策略)
      * Redis同步写入(保证实时性),数据库异步批量写入(提高性能)
      */
-    private void saveCart(WechatCartDTO cart) {
+    private void saveCart(CartDTO cart) {
         // 1. 同步保存到Redis(保证实时性)
         saveCartToRedis(cart);
 
@@ -983,7 +983,7 @@ public class CartServiceImpl implements CartService {
     /**
      * 保存购物车到Redis
      */
-    private void saveCartToRedis(WechatCartDTO cart) {
+    private void saveCartToRedis(CartDTO cart) {
         String cartKey = CART_KEY_PREFIX + cart.getTableId();
         String cartJson = JSON.toJSONString(cart);
         baseRedisService.setString(cartKey, cartJson, (long) CART_EXPIRE_SECONDS);
@@ -993,19 +993,19 @@ public class CartServiceImpl implements CartService {
      * 保存购物车到数据库(优化后的批量操作版本)
      * 使用批量逻辑删除和批量插入,提高性能
      */
-    private void saveCartToDatabase(WechatCartDTO cart) {
+    private void saveCartToDatabase(CartDTO cart) {
         try {
             Date now = new Date();
             Integer userId = TokenUtil.getCurrentUserId();
 
             // 1. 批量逻辑删除该桌号的所有购物车记录(使用 MyBatis-Plus 的 deleteBatchIds)
-            LambdaQueryWrapper<WechatStoreCart> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(WechatStoreCart::getTableId, cart.getTableId())
-                    .eq(WechatStoreCart::getDeleteFlag, 0);
-            List<WechatStoreCart> existingCartList = storeCartMapper.selectList(queryWrapper);
+            LambdaQueryWrapper<StoreCart> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(StoreCart::getTableId, cart.getTableId())
+                    .eq(StoreCart::getDeleteFlag, 0);
+            List<StoreCart> existingCartList = storeCartMapper.selectList(queryWrapper);
             if (existingCartList != null && !existingCartList.isEmpty()) {
                 List<Integer> cartIds = existingCartList.stream()
-                        .map(WechatStoreCart::getId)
+                        .map(StoreCart::getId)
                         .collect(Collectors.toList());
                 // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
                 storeCartMapper.deleteBatchIds(cartIds);
@@ -1013,9 +1013,9 @@ public class CartServiceImpl implements CartService {
 
             // 2. 批量插入新的购物车记录
             if (cart.getItems() != null && !cart.getItems().isEmpty()) {
-                List<WechatStoreCart> cartList = new ArrayList<>(cart.getItems().size());
-                for (WechatCartItemDTO item : cart.getItems()) {
-                    WechatStoreCart storeCart = new WechatStoreCart();
+                List<StoreCart> cartList = new ArrayList<>(cart.getItems().size());
+                for (CartItemDTO item : cart.getItems()) {
+                    StoreCart storeCart = new StoreCart();
                     storeCart.setTableId(cart.getTableId());
                     storeCart.setStoreId(cart.getStoreId());
                     storeCart.setCuisineId(item.getCuisineId());
@@ -1038,7 +1038,7 @@ public class CartServiceImpl implements CartService {
                 // 批量插入(如果数量较少,直接循环插入;如果数量较多,可以考虑分批插入)
                 if (cartList.size() <= 50) {
                     // 小批量直接插入
-                    for (WechatStoreCart storeCart : cartList) {
+                    for (StoreCart storeCart : cartList) {
                         storeCartMapper.insert(storeCart);
                     }
                 } else {
@@ -1046,8 +1046,8 @@ public class CartServiceImpl implements CartService {
                     int batchSize = 50;
                     for (int i = 0; i < cartList.size(); i += batchSize) {
                         int end = Math.min(i + batchSize, cartList.size());
-                        List<WechatStoreCart> batch = cartList.subList(i, end);
-                        for (WechatStoreCart storeCart : batch) {
+                        List<StoreCart> batch = cartList.subList(i, end);
+                        for (StoreCart storeCart : batch) {
                             storeCartMapper.insert(storeCart);
                         }
                     }
@@ -1055,7 +1055,7 @@ public class CartServiceImpl implements CartService {
             }
 
             // 3. 更新桌号表的购物车统计
-            WechatStoreTable table = storeTableMapper.selectById(cart.getTableId());
+            StoreTable table = storeTableMapper.selectById(cart.getTableId());
             if (table != null) {
                 table.setCartItemCount(cart.getTotalQuantity());
                 table.setCartTotalAmount(cart.getTotalAmount());

+ 67 - 71
alien-dining/src/main/java/shop/alien/dining/service/impl/DiningServiceImpl.java

@@ -7,14 +7,10 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 import shop.alien.entity.store.*;
-import shop.alien.entity.store.wechat.*;
-import shop.alien.entity.store.dto.wechat.WechatCartDTO;
-import shop.alien.entity.store.dto.wechat.WechatCartItemDTO;
+import shop.alien.entity.store.dto.CartDTO;
+import shop.alien.entity.store.dto.CartItemDTO;
 import shop.alien.entity.store.vo.*;
-import shop.alien.entity.store.vo.wechat.WechatOrderConfirmVO;
-import shop.alien.entity.store.vo.wechat.WechatOrderSettlementVO;
 import shop.alien.mapper.*;
-import shop.alien.mapper.wechat.*;
 import shop.alien.dining.config.BaseRedisService;
 import shop.alien.dining.service.CartService;
 import shop.alien.dining.service.DiningService;
@@ -35,18 +31,18 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public class DiningServiceImpl implements DiningService {
 
-    private final WechatStoreTableMapper storeTableMapper;
+    private final StoreTableMapper storeTableMapper;
     private final StoreInfoMapper storeInfoMapper;
-    private final WechatStoreCuisineMapper storeCuisineMapper;
-    private final WechatStoreCuisineCategoryMapper storeCuisineCategoryMapper;
-    private final WechatStoreCuisineComboMapper storeCuisineComboMapper;
-    private final WechatStoreOrderDetailMapper storeOrderDetailMapper;
+    private final StoreCuisineMapper storeCuisineMapper;
+    private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
+    private final StoreCuisineComboMapper storeCuisineComboMapper;
+    private final StoreOrderDetailMapper storeOrderDetailMapper;
     private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
     private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
     private final CartService cartService;
     private final BaseRedisService baseRedisService;
     private final shop.alien.dining.service.StoreOrderService storeOrderService;
-    private final WechatStoreOrderMapper storeOrderMapper;
+    private final shop.alien.mapper.StoreOrderMapper storeOrderMapper;
     private final shop.alien.dining.service.OrderLockService orderLockService;
 
     @Override
@@ -54,7 +50,7 @@ public class DiningServiceImpl implements DiningService {
         if (tableId == null) {
             return new TableDiningStatusVO(null, false, null);
         }
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table == null) {
             return new TableDiningStatusVO(tableId, false, null);
         }
@@ -69,7 +65,7 @@ public class DiningServiceImpl implements DiningService {
     @Override
     public DiningPageInfoVO getDiningPageInfo(Integer tableId, Integer dinerCount) {
         log.info("获取点餐页面信息, tableId={}, dinerCount={}", tableId, dinerCount);
-        WechatStoreTable table = storeTableMapper.selectById(tableId);
+        StoreTable table = storeTableMapper.selectById(tableId);
         if (table == null) {
             throw new RuntimeException("桌号不存在");
         }
@@ -115,16 +111,16 @@ public class DiningServiceImpl implements DiningService {
             keyword = keyword.substring(0, 10);
         }
 
-        LambdaQueryWrapper<WechatStoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisine::getStoreId, storeId);
-        wrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCuisine::getShelfStatus, 1); // 只查询上架的
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, storeId);
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的
         if (StringUtils.hasText(keyword)) {
-            wrapper.like(WechatStoreCuisine::getName, keyword);
+            wrapper.like(StoreCuisine::getName, keyword);
         }
-        wrapper.orderByDesc(WechatStoreCuisine::getCreatedTime);
+        wrapper.orderByDesc(StoreCuisine::getCreatedTime);
 
-        List<WechatStoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
+        List<StoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
         return convertToCuisineListVO(cuisines, tableId);
     }
 
@@ -139,21 +135,21 @@ public class DiningServiceImpl implements DiningService {
             size = 12;
         }
 
-        LambdaQueryWrapper<WechatStoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisine::getStoreId, storeId);
-        wrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCuisine::getShelfStatus, 1); // 只查询上架的
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, storeId);
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的
         if (categoryId != null) {
             // 这里假设菜品表有category_id字段,如果没有需要关联查询
-            // wrapper.eq(WechatStoreCuisine::getCategoryId, categoryId);
+            // wrapper.eq(StoreCuisine::getCategoryId, categoryId);
         }
-        wrapper.orderByDesc(WechatStoreCuisine::getCreatedTime);
+        wrapper.orderByDesc(StoreCuisine::getCreatedTime);
 
         // 分页查询
         int offset = (page - 1) * size;
         wrapper.last("LIMIT " + offset + ", " + size);
 
-        List<WechatStoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
+        List<StoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
         return convertToCuisineListVO(cuisines, tableId);
     }
 
@@ -161,7 +157,7 @@ public class DiningServiceImpl implements DiningService {
     public CuisineDetailVO getCuisineDetail(Integer cuisineId, Integer tableId) {
         log.info("获取菜品详情, cuisineId={}, tableId={}", cuisineId, tableId);
 
-        WechatStoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
+        StoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
         if (cuisine == null) {
             throw new RuntimeException("菜品不存在");
         }
@@ -197,22 +193,22 @@ public class DiningServiceImpl implements DiningService {
         vo.setMonthlySales(getMonthlySales(cuisineId));
 
         // 获取购物车数量
-        WechatCartDTO cart = cartService.getCart(tableId);
+        CartDTO cart = cartService.getCart(tableId);
         if (cart.getItems() != null) {
-            Optional<WechatCartItemDTO> cartItem = cart.getItems().stream()
+            Optional<CartItemDTO> cartItem = cart.getItems().stream()
                     .filter(item -> item.getCuisineId().equals(cuisineId))
                     .findFirst();
-            vo.setCartQuantity(cartItem.map(WechatCartItemDTO::getQuantity).orElse(0));
+            vo.setCartQuantity(cartItem.map(CartItemDTO::getQuantity).orElse(0));
         } else {
             vo.setCartQuantity(0);
         }
 
         // 如果是套餐,获取套餐包含的菜品
         if (cuisine.getCuisineType() != null && cuisine.getCuisineType() == 2) {
-            LambdaQueryWrapper<WechatStoreCuisineCombo> comboWrapper = new LambdaQueryWrapper<>();
-            comboWrapper.eq(WechatStoreCuisineCombo::getCid, cuisineId);
-            comboWrapper.eq(WechatStoreCuisineCombo::getDeleteFlag, 0);
-            List<WechatStoreCuisineCombo> combos = storeCuisineComboMapper.selectList(comboWrapper);
+            LambdaQueryWrapper<StoreCuisineCombo> comboWrapper = new LambdaQueryWrapper<>();
+            comboWrapper.eq(StoreCuisineCombo::getCid, cuisineId);
+            comboWrapper.eq(StoreCuisineCombo::getDeleteFlag, 0);
+            List<StoreCuisineCombo> combos = storeCuisineComboMapper.selectList(comboWrapper);
 
             List<CuisineComboItemVO> comboItems = combos.stream().map(combo -> {
                 CuisineComboItemVO item = new CuisineComboItemVO();
@@ -220,7 +216,7 @@ public class DiningServiceImpl implements DiningService {
                 item.setQuantity(combo.getSnum());
                 item.setCategory(combo.getCategory());
                 // 查询菜品名称
-                WechatStoreCuisine comboCuisine = storeCuisineMapper.selectById(combo.getSid());
+                StoreCuisine comboCuisine = storeCuisineMapper.selectById(combo.getSid());
                 if (comboCuisine != null) {
                     item.setCuisineName(comboCuisine.getName());
                 }
@@ -326,7 +322,7 @@ public class DiningServiceImpl implements DiningService {
     }
 
     @Override
-    public WechatOrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId) {
+    public OrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId) {
         log.info("获取订单确认页面信息, tableId={}, dinerCount={}, userId={}", tableId, dinerCount, userId);
 
         // 获取点餐页面信息(就餐中且未传人数时,内部会使用桌台已保存的就餐人数)
@@ -335,26 +331,26 @@ public class DiningServiceImpl implements DiningService {
                 ? pageInfo.getDinerCount() : (dinerCount != null ? dinerCount : 0);
 
         // 获取购物车
-        WechatCartDTO cart = cartService.getCart(tableId);
+        CartDTO cart = cartService.getCart(tableId);
 
         // 为购物车项补全菜品标签(购物车从 DB 加载时可能无 tags)
-        List<WechatCartItemDTO> items = cart.getItems();
+        List<CartItemDTO> items = cart.getItems();
         if (items != null && !items.isEmpty()) {
             Set<Integer> cuisineIds = items.stream()
-                    .map(WechatCartItemDTO::getCuisineId)
+                    .map(CartItemDTO::getCuisineId)
                     .filter(Objects::nonNull)
                     .collect(Collectors.toSet());
             if (!cuisineIds.isEmpty()) {
-                List<WechatStoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
+                List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
                 Map<Integer, String> tagsMap = new HashMap<>();
                 if (cuisines != null) {
-                    for (WechatStoreCuisine c : cuisines) {
+                    for (StoreCuisine c : cuisines) {
                         if (c.getTags() != null) {
                             tagsMap.put(c.getId(), c.getTags());
                         }
                     }
                 }
-                for (WechatCartItemDTO item : items) {
+                for (CartItemDTO item : items) {
                     if (item.getCuisineId() != null && item.getTags() == null) {
                         item.setTags(tagsMap.get(item.getCuisineId()));
                     }
@@ -366,7 +362,7 @@ public class DiningServiceImpl implements DiningService {
         Integer lockUserId = orderLockService.checkOrderLock(tableId);
         boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
 
-        WechatOrderConfirmVO vo = new WechatOrderConfirmVO();
+        OrderConfirmVO vo = new OrderConfirmVO();
         vo.setStoreName(pageInfo.getStoreName());
         vo.setTableNumber(pageInfo.getTableNumber());
         vo.setDinerCount(pageInfo.getDinerCount() != null ? pageInfo.getDinerCount() : dinerCount);
@@ -458,18 +454,18 @@ public class DiningServiceImpl implements DiningService {
     /**
      * 转换为菜品列表VO
      */
-    private List<CuisineListVO> convertToCuisineListVO(List<WechatStoreCuisine> cuisines, Integer tableId) {
+    private List<CuisineListVO> convertToCuisineListVO(List<StoreCuisine> cuisines, Integer tableId) {
         // 获取购物车
-        WechatCartDTO cart = cartService.getCart(tableId);
+        CartDTO cart = cartService.getCart(tableId);
         Map<Integer, Integer> cartQuantityMap = new HashMap<>();
         if (cart.getItems() != null) {
             cartQuantityMap = cart.getItems().stream()
-                    .collect(Collectors.toMap(WechatCartItemDTO::getCuisineId, WechatCartItemDTO::getQuantity));
+                    .collect(Collectors.toMap(CartItemDTO::getCuisineId, CartItemDTO::getQuantity));
         }
 
         // 批量查询月售数量
         Map<Integer, Integer> monthlySalesMap = new HashMap<>();
-        for (WechatStoreCuisine cuisine : cuisines) {
+        for (StoreCuisine cuisine : cuisines) {
             monthlySalesMap.put(cuisine.getId(), getMonthlySales(cuisine.getId()));
         }
 
@@ -512,16 +508,16 @@ public class DiningServiceImpl implements DiningService {
             Date monthStart = calendar.getTime();
 
             // 查询订单明细中该菜品的销售数量
-            LambdaQueryWrapper<WechatStoreOrderDetail> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(WechatStoreOrderDetail::getCuisineId, cuisineId);
-            wrapper.eq(WechatStoreOrderDetail::getDeleteFlag, 0);
-            wrapper.ge(WechatStoreOrderDetail::getCreatedTime, monthStart);
+            LambdaQueryWrapper<StoreOrderDetail> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(StoreOrderDetail::getCuisineId, cuisineId);
+            wrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
+            wrapper.ge(StoreOrderDetail::getCreatedTime, monthStart);
             // 只统计已支付的订单
-            wrapper.inSql(WechatStoreOrderDetail::getOrderId,
-                    "SELECT id FROM wechat_store_order WHERE pay_status = 1 AND delete_flag = 0");
+            wrapper.inSql(StoreOrderDetail::getOrderId,
+                    "SELECT id FROM store_order WHERE pay_status = 1 AND delete_flag = 0");
 
-            List<WechatStoreOrderDetail> details = storeOrderDetailMapper.selectList(wrapper);
-            return details.stream().mapToInt(WechatStoreOrderDetail::getQuantity).sum();
+            List<StoreOrderDetail> details = storeOrderDetailMapper.selectList(wrapper);
+            return details.stream().mapToInt(StoreOrderDetail::getQuantity).sum();
         } catch (Exception e) {
             log.error("获取月售数量失败, cuisineId={}", cuisineId, e);
             return 0;
@@ -529,32 +525,32 @@ public class DiningServiceImpl implements DiningService {
     }
 
     @Override
-    public WechatOrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId) {
+    public shop.alien.entity.store.vo.OrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId) {
         log.info("获取订单结算确认页面信息, orderId={}, userId={}", orderId, userId);
 
         // 查询订单
-        shop.alien.entity.store.wechat.WechatStoreOrder order = storeOrderService.getOrderById(orderId);
+        shop.alien.entity.store.StoreOrder order = storeOrderService.getOrderById(orderId);
         if (order == null) {
             throw new RuntimeException("订单不存在");
         }
 
         // 查询订单明细
-        LambdaQueryWrapper<shop.alien.entity.store.wechat.WechatStoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-        detailWrapper.eq(shop.alien.entity.store.wechat.WechatStoreOrderDetail::getOrderId, orderId);
-        detailWrapper.eq(shop.alien.entity.store.wechat.WechatStoreOrderDetail::getDeleteFlag, 0);
-        detailWrapper.orderByDesc(shop.alien.entity.store.wechat.WechatStoreOrderDetail::getCreatedTime);
-        List<shop.alien.entity.store.wechat.WechatStoreOrderDetail> details = storeOrderDetailMapper.selectList(detailWrapper);
+        LambdaQueryWrapper<shop.alien.entity.store.StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
+        detailWrapper.eq(shop.alien.entity.store.StoreOrderDetail::getOrderId, orderId);
+        detailWrapper.eq(shop.alien.entity.store.StoreOrderDetail::getDeleteFlag, 0);
+        detailWrapper.orderByDesc(shop.alien.entity.store.StoreOrderDetail::getCreatedTime);
+        List<shop.alien.entity.store.StoreOrderDetail> details = storeOrderDetailMapper.selectList(detailWrapper);
 
         // 批量查询菜品标签
         Set<Integer> cuisineIds = details.stream()
-                .map(shop.alien.entity.store.wechat.WechatStoreOrderDetail::getCuisineId)
+                .map(shop.alien.entity.store.StoreOrderDetail::getCuisineId)
                 .filter(Objects::nonNull)
                 .collect(Collectors.toSet());
         Map<Integer, String> cuisineIdToTags = new HashMap<>();
         if (!cuisineIds.isEmpty()) {
-            List<WechatStoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
+            List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
             if (cuisines != null) {
-                for (WechatStoreCuisine c : cuisines) {
+                for (StoreCuisine c : cuisines) {
                     if (c.getTags() != null) {
                         cuisineIdToTags.put(c.getId(), c.getTags());
                     }
@@ -562,10 +558,10 @@ public class DiningServiceImpl implements DiningService {
             }
         }
 
-        // 转换为 WechatCartItemDTO(含菜品标签)
+        // 转换为CartItemDTO(含菜品标签)
         Map<Integer, String> finalTagsMap = cuisineIdToTags;
-        List<WechatCartItemDTO> items = details.stream().map(detail -> {
-            WechatCartItemDTO item = new WechatCartItemDTO();
+        List<shop.alien.entity.store.dto.CartItemDTO> items = details.stream().map(detail -> {
+            shop.alien.entity.store.dto.CartItemDTO item = new shop.alien.entity.store.dto.CartItemDTO();
             item.setCuisineId(detail.getCuisineId());
             item.setCuisineName(detail.getCuisineName());
             item.setCuisineType(detail.getCuisineType());
@@ -587,7 +583,7 @@ public class DiningServiceImpl implements DiningService {
         Integer lockUserId = orderLockService.checkSettlementLock(orderId);
         boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
 
-        WechatOrderSettlementVO vo = new WechatOrderSettlementVO();
+        shop.alien.entity.store.vo.OrderSettlementVO vo = new shop.alien.entity.store.vo.OrderSettlementVO();
         vo.setOrderId(order.getId());
         vo.setOrderNo(order.getOrderNo());
         vo.setStoreName(storeInfo != null ? storeInfo.getStoreName() : null);

+ 2 - 2
alien-dining/src/main/java/shop/alien/dining/service/impl/OrderLockServiceImpl.java

@@ -18,8 +18,8 @@ import shop.alien.dining.service.OrderLockService;
 @RequiredArgsConstructor
 public class OrderLockServiceImpl implements OrderLockService {
 
-    private static final String ORDER_LOCK_KEY_PREFIX = "wechat:order:lock:table:";
-    private static final String SETTLEMENT_LOCK_KEY_PREFIX = "wechat:settlement:lock:order:";
+    private static final String ORDER_LOCK_KEY_PREFIX = "order:lock:table:";
+    private static final String SETTLEMENT_LOCK_KEY_PREFIX = "settlement:lock:order:";
     private static final int ORDER_LOCK_EXPIRE_SECONDS = 300; // 5分钟过期
 
     private final BaseRedisService baseRedisService;

+ 59 - 59
alien-dining/src/main/java/shop/alien/dining/service/impl/StoreInfoServiceImpl.java

@@ -5,16 +5,16 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCategory;
+import shop.alien.entity.store.StoreCuisine;
+import shop.alien.entity.store.StoreCuisineCategory;
 import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.wechat.WechatStoreTable;
-import shop.alien.entity.store.dto.wechat.WechatStoreInfoWithHomepageCuisinesDTO;
-import shop.alien.entity.store.vo.wechat.WechatCategoryWithCuisinesVO;
-import shop.alien.mapper.wechat.WechatStoreCuisineCategoryMapper;
-import shop.alien.mapper.wechat.WechatStoreCuisineMapper;
+import shop.alien.entity.store.StoreTable;
+import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
+import shop.alien.mapper.StoreCuisineCategoryMapper;
+import shop.alien.mapper.StoreCuisineMapper;
 import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.wechat.WechatStoreTableMapper;
+import shop.alien.mapper.StoreTableMapper;
 import shop.alien.dining.service.StoreInfoService;
 import org.apache.commons.lang3.StringUtils;
 
@@ -33,55 +33,55 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public class StoreInfoServiceImpl implements StoreInfoService {
 
-    private final WechatStoreTableMapper storeTableMapper;
-    private final WechatStoreCuisineCategoryMapper storeCuisineCategoryMapper;
-    private final WechatStoreCuisineMapper storeCuisineMapper;
+    private final StoreTableMapper storeTableMapper;
+    private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
+    private final StoreCuisineMapper storeCuisineMapper;
     private final StoreInfoMapper storeInfoMapper;
 
     @Override
-    public List<WechatStoreTable> getTablesByStoreId(Integer storeId) {
+    public List<StoreTable> getTablesByStoreId(Integer storeId) {
         log.info("根据门店ID查询桌号列表, storeId={}", storeId);
         
-        LambdaQueryWrapper<WechatStoreTable> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreTable::getStoreId, storeId);
-        wrapper.eq(WechatStoreTable::getDeleteFlag, 0);
-        wrapper.orderByAsc(WechatStoreTable::getTableNumber);
+        LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreTable::getStoreId, storeId);
+        wrapper.eq(StoreTable::getDeleteFlag, 0);
+        wrapper.orderByAsc(StoreTable::getTableNumber);
         
         return storeTableMapper.selectList(wrapper);
     }
 
     @Override
-    public List<WechatStoreCuisineCategory> getCategoriesByStoreId(Integer storeId) {
+    public List<StoreCuisineCategory> getCategoriesByStoreId(Integer storeId) {
         log.info("根据门店ID查询菜品种类列表, storeId={}", storeId);
         
-        LambdaQueryWrapper<WechatStoreCuisineCategory> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisineCategory::getStoreId, storeId);
-        wrapper.eq(WechatStoreCuisineCategory::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCuisineCategory::getStatus, 1); // 只查询启用的分类
-        wrapper.orderByAsc(WechatStoreCuisineCategory::getSort); // 按排序字段排序
+        LambdaQueryWrapper<StoreCuisineCategory> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisineCategory::getStoreId, storeId);
+        wrapper.eq(StoreCuisineCategory::getDeleteFlag, 0);
+        wrapper.eq(StoreCuisineCategory::getStatus, 1); // 只查询启用的分类
+        wrapper.orderByAsc(StoreCuisineCategory::getSort); // 按排序字段排序
         
         return storeCuisineCategoryMapper.selectList(wrapper);
     }
 
     @Override
-    public List<WechatStoreCuisine> getCuisinesByCategoryId(Integer categoryId) {
+    public List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId) {
         log.info("根据菜品种类ID查询菜品信息列表, categoryId={}", categoryId);
         
         // 先查询分类信息,获取 storeId
-        WechatStoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
+        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
         if (category == null) {
             log.warn("菜品种类不存在, categoryId={}", categoryId);
             return new java.util.ArrayList<>();
         }
         
         // 查询该门店下所有上架的菜品(与 getCategoriesWithCuisinesByStoreId 中 cuisines 查询条件、排序一致)
-        LambdaQueryWrapper<WechatStoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisine::getStoreId, category.getStoreId());
-        wrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCuisine::getShelfStatus, 1); // 只查询上架的菜品
-        wrapper.orderByAsc(WechatStoreCuisine::getId); // 与 categories-with-cuisines 中 cuisines 顺序一致
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, category.getStoreId());
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的菜品
+        wrapper.orderByAsc(StoreCuisine::getId); // 与 categories-with-cuisines 中 cuisines 顺序一致
         
-        List<WechatStoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
+        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
         
         // 过滤出包含该分类ID的菜品
         // categoryIds 是 JSON 数组格式,如:[1,2,3]
@@ -106,37 +106,37 @@ public class StoreInfoServiceImpl implements StoreInfoService {
     }
 
     @Override
-    public List<WechatCategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword) {
+    public List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword) {
         log.info("根据门店ID查询菜品种类及下属菜品, storeId={}, keyword={}", storeId, keyword);
-        List<WechatStoreCuisineCategory> categories = getCategoriesByStoreId(storeId);
+        List<StoreCuisineCategory> categories = getCategoriesByStoreId(storeId);
         if (categories == null || categories.isEmpty()) {
             return new ArrayList<>();
         }
         // 与 getCuisinesByCategoryId 相同的查询条件与排序,保证 cuisines 字段与 /store/info/cuisines 一致
-        LambdaQueryWrapper<WechatStoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
-        cuisineWrapper.eq(WechatStoreCuisine::getStoreId, storeId);
-        cuisineWrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        cuisineWrapper.eq(WechatStoreCuisine::getShelfStatus, 1);
-        cuisineWrapper.orderByAsc(WechatStoreCuisine::getId);
-        List<WechatStoreCuisine> allCuisines = storeCuisineMapper.selectList(cuisineWrapper);
+        LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
+        cuisineWrapper.eq(StoreCuisine::getStoreId, storeId);
+        cuisineWrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        cuisineWrapper.eq(StoreCuisine::getShelfStatus, 1);
+        cuisineWrapper.orderByAsc(StoreCuisine::getId);
+        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(cuisineWrapper);
         if (allCuisines == null) {
             allCuisines = new ArrayList<>();
         }
         boolean filterByName = StringUtils.isNotBlank(keyword);
         String keywordLower = filterByName ? keyword.trim().toLowerCase() : null;
-        List<WechatCategoryWithCuisinesVO> result = new ArrayList<>();
-        for (WechatStoreCuisineCategory category : categories) {
+        List<CategoryWithCuisinesVO> result = new ArrayList<>();
+        for (StoreCuisineCategory category : categories) {
             Integer categoryId = category.getId();
-            List<WechatStoreCuisine> cuisines = allCuisines.stream()
+            List<StoreCuisine> cuisines = allCuisines.stream()
                     .filter(c -> belongsToCategory(c, categoryId))
                     .filter(c -> !filterByName || (c.getName() != null && c.getName().toLowerCase().contains(keywordLower)))
                     .collect(Collectors.toList());
-            result.add(new WechatCategoryWithCuisinesVO(category, cuisines));
+            result.add(new CategoryWithCuisinesVO(category, cuisines));
         }
         return result;
     }
 
-    private boolean belongsToCategory(WechatStoreCuisine cuisine, Integer categoryId) {
+    private boolean belongsToCategory(StoreCuisine cuisine, Integer categoryId) {
         String categoryIdsStr = cuisine.getCategoryIds();
         if (StringUtils.isBlank(categoryIdsStr)) {
             return false;
@@ -156,19 +156,19 @@ public class StoreInfoServiceImpl implements StoreInfoService {
             log.warn("删除菜品种类失败:分类ID为空");
             return false;
         }
-        WechatStoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
+        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
         if (category == null) {
             log.warn("删除菜品种类失败:分类不存在, categoryId={}", categoryId);
             return false;
         }
         Integer storeId = category.getStoreId();
         // 1. 解除绑定:将该分类ID从所有关联菜品的 category_ids 中移除,价目表菜品其它字段不变
-        LambdaQueryWrapper<WechatStoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisine::getStoreId, storeId);
-        wrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        List<WechatStoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, storeId);
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
         if (allCuisines != null) {
-            for (WechatStoreCuisine cuisine : allCuisines) {
+            for (StoreCuisine cuisine : allCuisines) {
                 if (!belongsToCategory(cuisine, categoryId)) {
                     continue;
                 }
@@ -205,7 +205,7 @@ public class StoreInfoServiceImpl implements StoreInfoService {
     }
 
     @Override
-    public WechatStoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId) {
+    public StoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId) {
         log.info("根据商铺ID查询店铺信息和首页展示美食价目表, storeId={}", storeId);
         
         // 1. 查询店铺信息
@@ -215,21 +215,21 @@ public class StoreInfoServiceImpl implements StoreInfoService {
         }
         
         // 2. 查询首页展示的美食价目表(is_homepage_display = 1,上架状态 = 1,审核通过 = 1)
-        LambdaQueryWrapper<WechatStoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStoreCuisine::getStoreId, storeId);
-        wrapper.eq(WechatStoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(WechatStoreCuisine::getIsHomepageDisplay, 1); // 首页展示
-        wrapper.eq(WechatStoreCuisine::getShelfStatus, 1); // 上架状态
-        wrapper.eq(WechatStoreCuisine::getStatus, 1); // 审核通过
-        wrapper.orderByDesc(WechatStoreCuisine::getCreatedTime); // 按创建时间倒序
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, storeId);
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        wrapper.eq(StoreCuisine::getIsHomepageDisplay, 1); // 首页展示
+        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 上架状态
+        wrapper.eq(StoreCuisine::getStatus, 1); // 审核通过
+        wrapper.orderByDesc(StoreCuisine::getCreatedTime); // 按创建时间倒序
         
-        List<WechatStoreCuisine> homepageCuisines = storeCuisineMapper.selectList(wrapper);
+        List<StoreCuisine> homepageCuisines = storeCuisineMapper.selectList(wrapper);
         if (homepageCuisines == null) {
             homepageCuisines = new ArrayList<>();
         }
         
         // 3. 构建返回DTO
-        WechatStoreInfoWithHomepageCuisinesDTO dto = new WechatStoreInfoWithHomepageCuisinesDTO();
+        StoreInfoWithHomepageCuisinesDTO dto = new StoreInfoWithHomepageCuisinesDTO();
         dto.setStoreInfo(storeInfo);
         dto.setHomepageCuisines(homepageCuisines);
         

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 254 - 256
alien-dining/src/main/java/shop/alien/dining/service/impl/StoreOrderServiceImpl.java


+ 1 - 1
alien-dining/src/main/java/shop/alien/dining/strategy/payment/PaymentStrategy.java

@@ -19,7 +19,7 @@ public interface PaymentStrategy {
      * @param subject 订单标题
      * @param payer 支付者 openid
      * @param orderNo 订单号
-     * @param storeId 店铺ID,本系统调用时必传,用于获取 WechatStorePaymentConfig
+     * @param storeId 店铺ID,本系统调用时必传,用于获取 StorePaymentConfig
      * @return 预支付订单信息
      * @throws Exception 生成异常
      */

+ 27 - 27
alien-dining/src/main/java/shop/alien/dining/strategy/payment/impl/WeChatPaymentMininProgramStrategyImpl.java

@@ -24,10 +24,10 @@ import shop.alien.dining.util.WXPayUtility;
 import shop.alien.dining.util.WeChatPayUtil;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeDiscountCouponUser;
-import shop.alien.entity.store.wechat.WechatStoreOrder;
-import shop.alien.entity.store.wechat.WechatStorePaymentConfig;
+import shop.alien.entity.store.StoreOrder;
+import shop.alien.entity.store.StorePaymentConfig;
 import shop.alien.mapper.LifeDiscountCouponUserMapper;
-import shop.alien.mapper.wechat.WechatStorePaymentConfigMapper;
+import shop.alien.mapper.StorePaymentConfigMapper;
 import shop.alien.util.common.constant.DiscountCouponEnum;
 import shop.alien.util.common.constant.PaymentEnum;
 
@@ -85,7 +85,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     private String searchOrderByOutTradeNoPath;
 
     private final StoreOrderService storeOrderService;
-    private final WechatStorePaymentConfigMapper storePaymentConfigMapper;
+    private final StorePaymentConfigMapper storePaymentConfigMapper;
     private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
     private final ObjectMapper objectMapper;
 
@@ -95,25 +95,25 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     /**
      * 根据店铺ID从 MySQL 获取支付配置(本系统内部调用时使用)
      */
-    private WechatStorePaymentConfig getConfigByStoreId(Integer storeId) {
+    private StorePaymentConfig getConfigByStoreId(Integer storeId) {
         if (storeId == null) {
             return null;
         }
-        LambdaQueryWrapper<WechatStorePaymentConfig> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStorePaymentConfig::getStoreId, storeId);
+        LambdaQueryWrapper<StorePaymentConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StorePaymentConfig::getStoreId, storeId);
         return storePaymentConfigMapper.selectOne(wrapper);
     }
 
     /**
      * 根据微信支付公钥序列号获取支付配置(外部回调如支付通知时使用,通过请求头 Wechatpay-Serial 判断)
      */
-    private WechatStorePaymentConfig getConfigByWechatPayPublicKeyId(String wechatPayPublicKeyId) {
+    private StorePaymentConfig getConfigByWechatPayPublicKeyId(String wechatPayPublicKeyId) {
         if (!StringUtils.hasText(wechatPayPublicKeyId)) {
             return null;
         }
-        LambdaQueryWrapper<WechatStorePaymentConfig> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(WechatStorePaymentConfig::getWechatPayPublicKeyId, wechatPayPublicKeyId);
-        List<WechatStorePaymentConfig> storePaymentConfigs = storePaymentConfigMapper.selectList(wrapper);
+        LambdaQueryWrapper<StorePaymentConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StorePaymentConfig::getWechatPayPublicKeyId, wechatPayPublicKeyId);
+        List<StorePaymentConfig> storePaymentConfigs = storePaymentConfigMapper.selectList(wrapper);
         if (storePaymentConfigs.isEmpty()) {
             return null;
         }
@@ -121,9 +121,9 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     }
 
     /**
-     * 从 WechatStorePaymentConfig 加载商户私钥
+     * 从 StorePaymentConfig 加载商户私钥
      */
-    private PrivateKey loadPrivateKeyFromConfig(WechatStorePaymentConfig config) {
+    private PrivateKey loadPrivateKeyFromConfig(StorePaymentConfig config) {
         if (config == null) {
             return null;
         }
@@ -138,9 +138,9 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     }
 
     /**
-     * 从 WechatStorePaymentConfig 加载微信支付公钥
+     * 从 StorePaymentConfig 加载微信支付公钥
      */
-    private PublicKey loadPublicKeyFromConfig(WechatStorePaymentConfig config) {
+    private PublicKey loadPublicKeyFromConfig(StorePaymentConfig config) {
         if (config == null) {
             return null;
         }
@@ -161,7 +161,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
             log.warn("createPrePayOrder 缺少 storeId,无法获取支付配置");
             return R.fail("店铺ID不能为空");
         }
-        WechatStorePaymentConfig config = getConfigByStoreId(storeId);
+        StorePaymentConfig config = getConfigByStoreId(storeId);
         if (config == null) {
             log.warn("未找到店铺支付配置 storeId={}", storeId);
             return R.fail("未找到该店铺的微信支付配置");
@@ -193,7 +193,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
         request.payer.openid = payer;
 
         String wechatOutTradeNo = orderNo;
-        WechatStoreOrder storeOrder = storeOrderService.getOrderByOrderNo(orderNo);
+        StoreOrder storeOrder = storeOrderService.getOrderByOrderNo(orderNo);
         log.info("createPrePayOrder, orderNo: {}, storeOrder: {}", orderNo, storeOrder);
         if (storeOrder != null ) {
             log.info("createPrePayOrder, orderNo: {}, storeOrder: {}", orderNo, storeOrder);
@@ -284,7 +284,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
             return R.success("OK");
         }
 
-        WechatStorePaymentConfig config = getConfigByWechatPayPublicKeyId(serial);
+        StorePaymentConfig config = getConfigByWechatPayPublicKeyId(serial);
         if (config == null) {
             log.warn("微信支付回调:未找到公钥序列号对应的店铺配置 serial={}", serial);
             return R.fail("未找到对应支付配置");
@@ -306,7 +306,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
 
         if (sign.verify(signatureBytes)) {
             final String notifyDataCopy = notifyData;
-            final WechatStorePaymentConfig configCopy = config;
+            final StorePaymentConfig configCopy = config;
             CompletableFuture.runAsync(() -> processNotifyBusiness(notifyDataCopy, configCopy));
             return R.success("OK");
         } else {
@@ -318,7 +318,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
      * 异步处理回调业务:解密并更新订单状态(文档建议应答后再处理业务,避免超时)
      * @param config 已通过 Wechatpay-Serial 解析得到的店铺支付配置,内含 apiV3Key
      */
-    private void processNotifyBusiness(String notifyData, WechatStorePaymentConfig config) {
+    private void processNotifyBusiness(String notifyData, StorePaymentConfig config) {
         try {
             if (config == null || !StringUtils.hasText(config.getApiV3Key())) {
                 log.warn("微信支付回调:无可用 apiV3Key 无法解密");
@@ -346,9 +346,9 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
             String tradeState = jsonObject.getString("trade_state");
             if ("SUCCESS".equals(tradeState)) {
                 String outTradeNo = jsonObject.getString("out_trade_no");
-                WechatStoreOrder storeOrder = storeOrderService.getOne(new QueryWrapper<WechatStoreOrder>().eq("order_no", outTradeNo));
+                StoreOrder storeOrder = storeOrderService.getOne(new QueryWrapper<StoreOrder>().eq("order_no", outTradeNo));
                 if (storeOrder == null && StringUtils.hasText(outTradeNo)) {
-                    storeOrder = storeOrderService.getOne(new QueryWrapper<WechatStoreOrder>().eq("pay_trade_no", outTradeNo));
+                    storeOrder = storeOrderService.getOne(new QueryWrapper<StoreOrder>().eq("pay_trade_no", outTradeNo));
                 }
                 if (storeOrder != null && storeOrder.getPayStatus() != 1) {
                     storeOrder.setPayStatus(1);
@@ -395,7 +395,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
         if (storeId == null) {
             return R.fail("店铺ID不能为空");
         }
-        WechatStorePaymentConfig config = getConfigByStoreId(storeId);
+        StorePaymentConfig config = getConfigByStoreId(storeId);
         if (config == null) {
             return R.fail("未找到该店铺的微信支付配置");
         }
@@ -417,7 +417,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     }
 
     public DirectAPIv3QueryResponse searchOrderRun(QueryByWxTradeNoRequest request,
-                                                   WechatStorePaymentConfig config,
+                                                   StorePaymentConfig config,
                                                    PrivateKey privateKey,
                                                    PublicKey wechatPayPublicKey) {
         String uri = searchOrderByOutTradeNoPath;
@@ -467,7 +467,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
         if (storeId == null) {
             return R.fail("店铺ID不能为空");
         }
-        WechatStorePaymentConfig config = getConfigByStoreId(storeId);
+        StorePaymentConfig config = getConfigByStoreId(storeId);
         if (config == null) {
             return R.fail("未找到该店铺的微信支付配置");
         }
@@ -540,7 +540,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     }
 
     public Refund doSearchRefundRecordByOutRefundNo(QueryByOutRefundNoRequest request,
-                                                   WechatStorePaymentConfig config,
+                                                   StorePaymentConfig config,
                                                    PrivateKey privateKey,
                                                    PublicKey wechatPayPublicKey) {
         String uri = searchRefundStatusByOutRefundNoPath;
@@ -568,7 +568,7 @@ public class WeChatPaymentMininProgramStrategyImpl implements PaymentStrategy {
     }
 
     public DirectAPIv3JsapiPrepayResponse doCreatePrePayOrder(DirectAPIv3JsapiPrepayRequest request,
-                                                             WechatStorePaymentConfig config,
+                                                             StorePaymentConfig config,
                                                              PrivateKey privateKey) {
         String uri = prePayPath;
         String reqBody = WXPayUtility.toJson(request);

+ 0 - 32
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatAddCartItemDTO.java

@@ -1,32 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
-
-/**
- * 小程序点餐-添加购物车商品(自 {@link shop.alien.entity.store.dto.AddCartItemDTO} 复制)
- */
-@Data
-@ApiModel(value = "WechatAddCartItemDTO", description = "小程序添加购物车商品")
-public class WechatAddCartItemDTO {
-
-    @ApiModelProperty(value = "桌号ID", required = true)
-    @NotNull(message = "桌号ID不能为空")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "菜品ID", required = true)
-    @NotNull(message = "菜品ID不能为空")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "数量", required = true)
-    @NotNull(message = "数量不能为空")
-    @Positive(message = "数量必须大于0")
-    private Integer quantity;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-}

+ 0 - 34
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCartDTO.java

@@ -1,34 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 小程序点餐-购物车(字段自 {@link shop.alien.entity.store.dto.CartDTO} 复制)
- */
-@Data
-@ApiModel(value = "WechatCartDTO", description = "小程序点餐购物车")
-public class WechatCartDTO {
-
-    @ApiModelProperty(value = "桌号ID")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "门店ID")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "购物车商品列表")
-    private List<WechatCartItemDTO> items;
-
-    @ApiModelProperty(value = "总金额")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "商品总数量")
-    private Integer totalQuantity;
-}

+ 0 - 51
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCartItemDTO.java

@@ -1,51 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-/**
- * 小程序点餐-购物车商品项(字段自 {@link shop.alien.entity.store.dto.CartItemDTO} 复制,可独立演进)
- */
-@Data
-@ApiModel(value = "WechatCartItemDTO", description = "小程序点餐购物车商品项")
-public class WechatCartItemDTO {
-
-    @ApiModelProperty(value = "菜品ID")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品类型(1:单品, 2:套餐)")
-    private Integer cuisineType;
-
-    @ApiModelProperty(value = "菜品图片")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "单价")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "数量")
-    private Integer quantity;
-
-    @ApiModelProperty(value = "已下单数量(下单时锁定的数量,不允许减少或删除)")
-    private Integer lockedQuantity;
-
-    @ApiModelProperty(value = "小计金额")
-    private BigDecimal subtotalAmount;
-
-    @ApiModelProperty(value = "添加该菜品的用户ID")
-    private Integer addUserId;
-
-    @ApiModelProperty(value = "添加该菜品的用户手机号")
-    private String addUserPhone;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    @ApiModelProperty(value = "菜品标签(JSON数组,如:[\"招牌菜\",\"推荐\"])")
-    private String tags;
-}

+ 0 - 26
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatChangeTableDTO.java

@@ -1,26 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-
-/**
- * 小程序点餐-换桌(自 {@link shop.alien.entity.store.dto.ChangeTableDTO} 复制)
- */
-@Data
-@ApiModel(value = "WechatChangeTableDTO", description = "小程序换桌")
-public class WechatChangeTableDTO {
-
-    @ApiModelProperty(value = "原桌号ID", required = true)
-    @NotNull(message = "原桌号ID不能为空")
-    private Integer fromTableId;
-
-    @ApiModelProperty(value = "目标桌号ID", required = true)
-    @NotNull(message = "目标桌号ID不能为空")
-    private Integer toTableId;
-
-    @ApiModelProperty(value = "换桌原因")
-    private String changeReason;
-}

+ 0 - 47
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatCreateOrderDTO.java

@@ -1,47 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import java.math.BigDecimal;
-
-/**
- * 小程序点餐-创建订单 DTO(自 {@link shop.alien.entity.store.dto.CreateOrderDTO} 复制)
- */
-@Data
-@ApiModel(value = "WechatCreateOrderDTO", description = "小程序创建订单")
-public class WechatCreateOrderDTO {
-
-    @ApiModelProperty(value = "桌号ID", required = true)
-    @NotNull(message = "桌号ID不能为空")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "优惠券ID(可选,不选择优惠券时传 null 或不传此字段)")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "订单总金额(前端传参,不做后台校验)")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "餐具费(前端传参,不做后台校验)")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "优惠金额(前端传参,不做后台校验)")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "实付金额(前端传参,不做后台校验)")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "联系电话")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "备注(限30字)。创建/更新订单时传入;更新订单(加餐)时为覆盖,不拼接")
-    private String remark;
-
-    @ApiModelProperty(value = "是否立即支付(0:否,创建订单但不支付; 1:是,创建订单并支付)")
-    private Integer immediatePay;
-}

+ 0 - 23
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatStoreInfoWithHomepageCuisinesDTO.java

@@ -1,23 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-
-import java.util.List;
-
-/**
- * 小程序点餐-店铺信息和首页展示美食价目表(自 {@link shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO} 复制,价目表为 {@link WechatStoreCuisine})
- */
-@Data
-@ApiModel(value = "WechatStoreInfoWithHomepageCuisinesDTO", description = "小程序-店铺信息和首页展示美食价目表")
-public class WechatStoreInfoWithHomepageCuisinesDTO {
-
-    @ApiModelProperty(value = "店铺信息")
-    private StoreInfo storeInfo;
-
-    @ApiModelProperty(value = "首页展示的美食价目表列表(WechatStoreCuisine)")
-    private List<WechatStoreCuisine> homepageCuisines;
-}

+ 0 - 22
alien-entity/src/main/java/shop/alien/entity/store/dto/wechat/WechatUpdateOrderCouponDTO.java

@@ -1,22 +0,0 @@
-package shop.alien.entity.store.dto.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-
-/**
- * 小程序点餐-更新订单优惠券(自 {@link shop.alien.entity.store.dto.UpdateOrderCouponDTO} 复制)
- */
-@Data
-@ApiModel(value = "WechatUpdateOrderCouponDTO", description = "小程序更新订单优惠券")
-public class WechatUpdateOrderCouponDTO {
-
-    @ApiModelProperty(value = "订单ID", required = true)
-    @NotNull(message = "订单ID不能为空")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "优惠券ID(可为空,表示不使用优惠券)")
-    private Integer couponId;
-}

+ 0 - 30
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatCategoryWithCuisinesVO.java

@@ -1,30 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCategory;
-
-import java.util.List;
-
-/**
- * 小程序点餐-菜品种类及其下属菜品 VO(自 {@link shop.alien.entity.store.vo.CategoryWithCuisinesVO} 复制,使用 wechat 实体类型)
- * <p>
- * category 与 GET /store/info/categories 单条字段一致(WechatStoreCuisineCategory);cuisines 与 GET /store/info/cuisines 列表元素一致(WechatStoreCuisine)。
- * </p>
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@ApiModel(value = "WechatCategoryWithCuisinesVO", description = "小程序-菜品种类及该分类下的菜品列表")
-public class WechatCategoryWithCuisinesVO {
-
-    @ApiModelProperty(value = "菜品种类信息(WechatStoreCuisineCategory)")
-    private WechatStoreCuisineCategory category;
-
-    @ApiModelProperty(value = "该分类下的菜品列表(WechatStoreCuisine)")
-    private List<WechatStoreCuisine> cuisines;
-}

+ 0 - 50
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderChangeLogBatchVO.java

@@ -1,50 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 小程序点餐-订单变更记录批次(自 {@link shop.alien.entity.store.vo.OrderChangeLogBatchVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderChangeLogBatchVO", description = "小程序订单变更记录批次")
-public class WechatOrderChangeLogBatchVO {
-
-    @ApiModelProperty(value = "批次号")
-    private String batchNo;
-
-    @ApiModelProperty(value = "操作类型(1:首次下单, 3:更新订单)")
-    private Integer operationType;
-
-    @ApiModelProperty(value = "操作类型文本")
-    private String operationTypeText;
-
-    @ApiModelProperty(value = "操作时间")
-    private Date operationTime;
-
-    @ApiModelProperty(value = "操作人ID")
-    private Integer operatorUserId;
-
-    @ApiModelProperty(value = "操作人手机号")
-    private String operatorUserPhone;
-
-    @ApiModelProperty(value = "备注(该批次对应的备注,如下单/更新订单时的备注)")
-    private String remark;
-
-    @ApiModelProperty(value = "该批次商品数量变化总和")
-    private Integer totalQuantityChange;
-
-    @ApiModelProperty(value = "该批次金额变化总和")
-    private BigDecimal totalAmountChange;
-
-    @ApiModelProperty(value = "该批次商品数量")
-    private Integer itemCount;
-
-    @ApiModelProperty(value = "该批次的商品明细列表")
-    private List<WechatOrderChangeLogItemVO> items;
-}

+ 0 - 48
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderChangeLogItemVO.java

@@ -1,48 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-/**
- * 小程序点餐-订单变更记录商品项(自 {@link shop.alien.entity.store.vo.OrderChangeLogItemVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderChangeLogItemVO", description = "小程序订单变更记录商品项")
-public class WechatOrderChangeLogItemVO {
-
-    @ApiModelProperty(value = "菜品ID")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品类型(1:单品, 2:套餐)")
-    private Integer cuisineType;
-
-    @ApiModelProperty(value = "菜品图片")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "单价")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "数量变化(新增的数量,正数表示增加,负数表示减少)")
-    private Integer quantityChange;
-
-    @ApiModelProperty(value = "变化前数量")
-    private Integer quantityBefore;
-
-    @ApiModelProperty(value = "变化后数量")
-    private Integer quantityAfter;
-
-    @ApiModelProperty(value = "金额变化")
-    private BigDecimal amountChange;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    @ApiModelProperty(value = "菜品标签(JSON数组,如:[\"招牌菜\",\"推荐\"])")
-    private String tags;
-}

+ 0 - 66
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderConfirmVO.java

@@ -1,66 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import shop.alien.entity.store.dto.wechat.WechatCartItemDTO;
-import shop.alien.entity.store.vo.AvailableCouponVO;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 小程序点餐-订单确认页(自 {@link shop.alien.entity.store.vo.OrderConfirmVO} 复制,购物车项为 {@link WechatCartItemDTO})
- */
-@Data
-@ApiModel(value = "WechatOrderConfirmVO", description = "小程序订单确认页面")
-public class WechatOrderConfirmVO {
-
-    @ApiModelProperty(value = "店铺名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "联系电话")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "备注(限30字)")
-    private String remark;
-
-    @ApiModelProperty(value = "购物车商品列表")
-    private List<WechatCartItemDTO> items;
-
-    @ApiModelProperty(value = "菜品总价")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "餐具费")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "餐具费单价")
-    private BigDecimal tablewareUnitPrice;
-
-    @ApiModelProperty(value = "优惠券ID")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "优惠券名称")
-    private String couponName;
-
-    @ApiModelProperty(value = "优惠金额")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "应付金额(菜品总价+餐具费-优惠券)")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "可用优惠券列表")
-    private List<AvailableCouponVO> availableCoupons;
-
-    @ApiModelProperty(value = "是否已锁定(有人正在下单)")
-    private Boolean isLocked;
-
-    @ApiModelProperty(value = "锁定用户ID")
-    private Integer lockUserId;
-}

+ 0 - 33
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderCuisineItemVO.java

@@ -1,33 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-
-/**
- * 小程序点餐-订单菜品项(自 {@link shop.alien.entity.store.vo.OrderCuisineItemVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderCuisineItemVO", description = "小程序订单菜品项")
-public class WechatOrderCuisineItemVO {
-
-    @ApiModelProperty(value = "菜品ID")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品图片")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "数量")
-    private Integer quantity;
-
-    @ApiModelProperty(value = "单价")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "菜品标签(JSON数组,如:[\"招牌菜\",\"推荐\"])")
-    private String tags;
-}

+ 0 - 74
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderDetailWithChangeLogVO.java

@@ -1,74 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 小程序点餐-订单详情含变更记录(自 {@link shop.alien.entity.store.vo.OrderDetailWithChangeLogVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderDetailWithChangeLogVO", description = "小程序订单详情(含变更记录)")
-public class WechatOrderDetailWithChangeLogVO {
-
-    @ApiModelProperty(value = "订单ID")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    private String orderNo;
-
-    @ApiModelProperty(value = "店铺名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "联系电话")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    @ApiModelProperty(value = "菜品总价")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "餐具费")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "优惠券ID")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "优惠券名称")
-    private String couponName;
-
-    @ApiModelProperty(value = "优惠金额")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "应付金额")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)")
-    private Integer orderStatus;
-
-    @ApiModelProperty(value = "支付状态(0:未支付, 1:已支付, 2:已退款)")
-    private Integer payStatus;
-
-    @ApiModelProperty(value = "支付方式(1:微信, 2:支付宝, 3:现金)")
-    private Integer payType;
-
-    @ApiModelProperty(value = "创建时间")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "支付时间")
-    private Date payTime;
-
-    @ApiModelProperty(value = "订单变更记录批次列表")
-    private List<WechatOrderChangeLogBatchVO> changeLogBatches;
-}

+ 0 - 105
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderInfoVO.java

@@ -1,105 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import shop.alien.entity.store.dto.wechat.WechatCartItemDTO;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 小程序点餐-订单信息(自 {@link shop.alien.entity.store.vo.OrderInfoVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderInfoVO", description = "小程序订单信息")
-public class WechatOrderInfoVO {
-
-    @ApiModelProperty(value = "订单ID")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    private String orderNo;
-
-    @ApiModelProperty(value = "店铺名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "店铺ID")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "门店电话")
-    private String storeTel;
-
-    @ApiModelProperty(value = "门店地址")
-    private String storeAddress;
-
-    @ApiModelProperty(value = "门店简介")
-    private String storeBlurb;
-
-    @ApiModelProperty(value = "门店类型(1:中餐, 2:烧烤, 3:饮品, 4:甜点, 5:火锅, 6:宵夜, 7:西餐, 8:轻食, 9:水果)")
-    private String storeType;
-
-    @ApiModelProperty(value = "营业状态(-1:注销中, 0:正常营业, 1:暂停营业, 2:筹建中, 99:永久关门)")
-    private Integer businessStatus;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "联系电话")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    @ApiModelProperty(value = "菜品清单")
-    private List<WechatCartItemDTO> items;
-
-    @ApiModelProperty(value = "菜品总价")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "餐具费")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "优惠券ID")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "优惠券名称")
-    private String couponName;
-
-    @ApiModelProperty(value = "优惠券类型:1-满减券,2-折扣券")
-    private Integer couponType;
-
-    @ApiModelProperty(value = "折扣率(0-100,用于折扣券,例如80表示8折)")
-    private BigDecimal discountRate;
-
-    @ApiModelProperty(value = "面值(用于满减券)")
-    private BigDecimal nominalValue;
-
-    @ApiModelProperty(value = "最低消费")
-    private BigDecimal minimumSpendingAmount;
-
-    @ApiModelProperty(value = "优惠金额")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "应付金额")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)")
-    private Integer orderStatus;
-
-    @ApiModelProperty(value = "支付状态(0:未支付, 1:已支付, 2:已退款)")
-    private Integer payStatus;
-
-    @ApiModelProperty(value = "支付方式(1:微信, 2:支付宝, 3:现金)")
-    private Integer payType;
-
-    @ApiModelProperty(value = "创建时间")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "支付时间")
-    private Date payTime;
-}

+ 0 - 65
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderSettlementVO.java

@@ -1,65 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import shop.alien.entity.store.dto.wechat.WechatCartItemDTO;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-/**
- * 小程序点餐-结算确认页(自 {@link shop.alien.entity.store.vo.OrderSettlementVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderSettlementVO", description = "小程序订单结算确认页面")
-public class WechatOrderSettlementVO {
-
-    @ApiModelProperty(value = "订单ID")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    private String orderNo;
-
-    @ApiModelProperty(value = "店铺名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "联系电话")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    @ApiModelProperty(value = "菜品清单")
-    private List<WechatCartItemDTO> items;
-
-    @ApiModelProperty(value = "菜品总价")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "餐具费")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "优惠券ID")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "优惠券名称")
-    private String couponName;
-
-    @ApiModelProperty(value = "优惠金额")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "应付金额")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "是否已锁定(有人正在结算)")
-    private Boolean isLocked;
-
-    @ApiModelProperty(value = "锁定用户ID")
-    private Integer lockUserId;
-}

+ 0 - 31
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatOrderSuccessVO.java

@@ -1,31 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-/**
- * 小程序点餐-下单成功页(自 {@link shop.alien.entity.store.vo.OrderSuccessVO} 复制)
- */
-@Data
-@ApiModel(value = "WechatOrderSuccessVO", description = "小程序下单成功")
-public class WechatOrderSuccessVO {
-
-    @ApiModelProperty(value = "订单ID")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    private String orderNo;
-
-    @ApiModelProperty(value = "店铺名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "桌号")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)")
-    private Integer orderStatus;
-}

+ 0 - 25
alien-entity/src/main/java/shop/alien/entity/store/vo/wechat/WechatStoreOrderPageVO.java

@@ -1,25 +0,0 @@
-package shop.alien.entity.store.vo.wechat;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import shop.alien.entity.store.wechat.WechatStoreOrder;
-
-import java.util.List;
-
-/**
- * 小程序点餐-订单分页 VO(自 {@link shop.alien.entity.store.vo.StoreOrderPageVO} 拆分,订单实体为 {@link WechatStoreOrder})
- */
-@Data
-@ApiModel(value = "WechatStoreOrderPageVO", description = "小程序订单分页(含菜品)")
-public class WechatStoreOrderPageVO {
-
-    @ApiModelProperty(value = "订单信息")
-    private WechatStoreOrder order;
-
-    @ApiModelProperty(value = "门店名称")
-    private String storeName;
-
-    @ApiModelProperty(value = "订单菜品列表")
-    private List<WechatOrderCuisineItemVO> cuisineItems;
-}

+ 0 - 99
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCart.java

@@ -1,99 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 购物车表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_cart")
-@ApiModel(value = "WechatStoreCart对象", description = "购物车表")
-public class WechatStoreCart {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "桌号ID")
-    @TableField("table_id")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "菜品ID")
-    @TableField("cuisine_id")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    @TableField("cuisine_name")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品图片")
-    @TableField("cuisine_image")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "单价")
-    @TableField("unit_price")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "数量")
-    @TableField("quantity")
-    private Integer quantity;
-
-    @ApiModelProperty(value = "已下单数量(下单时锁定的数量,不允许减少或删除)")
-    @TableField("locked_quantity")
-    private Integer lockedQuantity;
-
-    @ApiModelProperty(value = "小计金额")
-    @TableField("subtotal_amount")
-    private BigDecimal subtotalAmount;
-
-    @ApiModelProperty(value = "添加该菜品的用户ID")
-    @TableField("add_user_id")
-    private Integer addUserId;
-
-    @ApiModelProperty(value = "添加该菜品的用户手机号")
-    @TableField("add_user_phone")
-    private String addUserPhone;
-
-    @ApiModelProperty(value = "备注")
-    @TableField("remark")
-    private String remark;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 88
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCouponUsage.java

@@ -1,88 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 优惠券使用记录表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_coupon_usage")
-@ApiModel(value = "WechatStoreCouponUsage对象", description = "优惠券使用记录表")
-public class WechatStoreCouponUsage {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "桌号ID")
-    @TableField("table_id")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "订单ID(下单时关联)")
-    @TableField("order_id")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "优惠券ID")
-    @TableField("coupon_id")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "优惠券名称")
-    @TableField("coupon_name")
-    private String couponName;
-
-    @ApiModelProperty(value = "优惠金额")
-    @TableField("discount_amount")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "使用状态(0:已标记使用, 1:已下单, 2:已支付, 3:已取消)")
-    @TableField("usage_status")
-    private Integer usageStatus;
-
-    @ApiModelProperty(value = "换桌前的桌号ID(如果是换桌迁移)")
-    @TableField("from_table_id")
-    private Integer fromTableId;
-
-    @ApiModelProperty(value = "换桌迁移时间")
-    @TableField("migrate_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date migrateTime;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 143
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisine.java

@@ -1,143 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 美食价目表
- *
- * @author auto-generated
- * @since 2025-01-01
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_cuisine")
-@ApiModel(value = "WechatStoreCuisine对象", description = "美食价目表")
-public class WechatStoreCuisine {
-
-    @ApiModelProperty(value = "主键")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "商户id")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "美食类型: 1-单品,2-套餐")
-    @TableField("cuisine_type")
-    private Integer cuisineType;
-
-    @ApiModelProperty(value = "菜品分类ids(JSON数组,如:[1,2,3])")
-    @TableField("category_ids")
-    private String categoryIds;
-
-    @ApiModelProperty(value = "菜名")
-    @TableField("name")
-    private String name;
-
-    @ApiModelProperty(value = "总价")
-    @TableField("total_price")
-    private BigDecimal totalPrice;
-
-    @ApiModelProperty(value = "首页展示(0:否, 1:是)")
-    @TableField("is_homepage_display")
-    private Integer isHomepageDisplay;
-
-    @ApiModelProperty(value = "菜品标签(JSON数组,如:[\"招牌菜\",\"推荐\"])")
-    @TableField("tags")
-    private String tags;
-
-    @ApiModelProperty(value = "菜品短评")
-    @TableField("dish_review")
-    private String dishReview;
-
-    @ApiModelProperty(value = "图片列表,最多 9 张 URL")
-    @TableField("images")
-    private String images;
-
-    @ApiModelProperty(value = "图文详情-图片")
-    @TableField("image_content")
-    private String imageContent;
-
-    @ApiModelProperty(value = "菜品原料json(原料名称:name,所需重量:height,成本价:cost,推荐价格:suggest)")
-    @TableField("raw_json")
-    private String rawJson;
-
-    @ApiModelProperty(value = "图文详情-文字")
-    @TableField("detail_content")
-    private String detailContent;
-
-    @ApiModelProperty(value = "菜品描述")
-    @TableField("description")
-    private String description;
-
-    @ApiModelProperty(value = "补充说明")
-    @TableField("extra_note")
-    private String extraNote;
-
-    @ApiModelProperty(value = "是否需要预约:0=否,1=是")
-    @TableField("need_reserve")
-    private Integer needReserve;
-
-    @ApiModelProperty(value = "预约规则")
-    @TableField("reserve_rule")
-    private String reserveRule;
-
-    @ApiModelProperty(value = "适用人数")
-    @TableField("people_limit")
-    private String peopleLimit;
-
-    @ApiModelProperty(value = "使用规则")
-    @TableField("usage_rule")
-    private String usageRule;
-
-    @ApiModelProperty(value = "状态:0-待审核 1-审核通过 2-审核拒绝")
-    @TableField("status")
-    private Integer status;
-
-    @ApiModelProperty(value = "上下架状态:1-上架,2-下架")
-    @TableField("shelf_status")
-    private Integer shelfStatus;
-
-    @ApiModelProperty(value = "拒绝原因(审核失败原因)")
-    @TableField("rejection_reason")
-    private String rejectionReason;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建人")
-    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "更新人")
-    @TableField(value = "updated_user_id", fill = FieldFill.UPDATE)
-    private Integer updatedUserId;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "更新时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "AI审核时间")
-    @TableField(value = "audit_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date auditTime;
-
-}
-
-

+ 0 - 66
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisineCategory.java

@@ -1,66 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 菜品分类表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_cuisine_category")
-@ApiModel(value = "WechatStoreCuisineCategory对象", description = "菜品分类表")
-public class WechatStoreCuisineCategory {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "分类名称")
-    @TableField("category_name")
-    private String categoryName;
-
-    @ApiModelProperty(value = "状态(0:禁用, 1:启用)")
-    @TableField("status")
-    private Integer status;
-
-    @ApiModelProperty(value = "排序")
-    @TableField("sort")
-    private Integer sort;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 69
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreCuisineCombo.java

@@ -1,69 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 美食套餐表(辅助详情查询)
- *
- * @author auto-generated
- * @since 2025-01-01
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_cuisine_combo")
-@ApiModel(value = "WechatStoreCuisineCombo对象", description = "美食套餐表(辅助详情查询)")
-public class WechatStoreCuisineCombo {
-
-    @ApiModelProperty(value = "主键")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "单品id")
-    @TableField("sid")
-    private Integer sid;
-
-    @ApiModelProperty(value = "套餐id")
-    @TableField("cid")
-    private Integer cid;
-
-    @ApiModelProperty(value = "套餐包含该单品的数量")
-    @TableField("snum")
-    private Integer snum;
-
-    @ApiModelProperty(value = "类别")
-    @TableField("category")
-    private String category;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建人")
-    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "更新人")
-    @TableField(value = "updated_user_id", fill = FieldFill.UPDATE)
-    private Integer updatedUserId;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "更新时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-}
-
-
-

+ 0 - 141
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrder.java

@@ -1,141 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 订单表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_order")
-@ApiModel(value = "WechatStoreOrder对象", description = "订单表")
-public class WechatStoreOrder {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "订单号")
-    @TableField("order_no")
-    private String orderNo;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "桌号ID")
-    @TableField("table_id")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "桌号")
-    @TableField("table_number")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "就餐人数")
-    @TableField("diner_count")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "支付用户ID")
-    @TableField("pay_user_id")
-    private Integer payUserId;
-
-    @ApiModelProperty(value = "支付用户手机号")
-    @TableField("pay_user_phone")
-    private String payUserPhone;
-
-    @ApiModelProperty(value = "联系电话")
-    @TableField("contact_phone")
-    private String contactPhone;
-
-    @ApiModelProperty(value = "餐具费")
-    @TableField("tableware_fee")
-    private BigDecimal tablewareFee;
-
-    @ApiModelProperty(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)")
-    @TableField("order_status")
-    private Integer orderStatus;
-
-    @ApiModelProperty(value = "订单总金额")
-    @TableField("total_amount")
-    private BigDecimal totalAmount;
-
-    @ApiModelProperty(value = "优惠券ID")
-    @TableField("coupon_id")
-    private Integer couponId;
-
-    @ApiModelProperty(value = "当前使用的优惠券ID(用于换桌场景)")
-    @TableField("current_coupon_id")
-    private Integer currentCouponId;
-
-    @ApiModelProperty(value = "优惠金额")
-    @TableField("discount_amount")
-    private BigDecimal discountAmount;
-
-    @ApiModelProperty(value = "锁定用户ID(下单或结算时锁定)")
-    @TableField("lock_user_id")
-    private Integer lockUserId;
-
-    @ApiModelProperty(value = "锁定过期时间")
-    @TableField("lock_expire_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date lockExpireTime;
-
-    @ApiModelProperty(value = "实付金额")
-    @TableField("pay_amount")
-    private BigDecimal payAmount;
-
-    @ApiModelProperty(value = "支付方式(1:微信, 2:支付宝, 3:现金)")
-    @TableField("pay_type")
-    private Integer payType;
-
-    @ApiModelProperty(value = "支付状态(0:未支付, 1:已支付, 2:已退款)")
-    @TableField("pay_status")
-    private Integer payStatus;
-
-    @ApiModelProperty(value = "支付时间")
-    @TableField("pay_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date payTime;
-
-    @ApiModelProperty(value = "支付交易号")
-    @TableField("pay_trade_no")
-    private String payTradeNo;
-
-    @ApiModelProperty(value = "备注")
-    @TableField("remark")
-    private String remark;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 120
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderChangeLog.java

@@ -1,120 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 订单变更记录表(记录每次下单/更新订单的商品变化)
- *
- * @author system
- * @since 2025-02-02
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_order_change_log")
-@ApiModel(value = "WechatStoreOrderChangeLog对象", description = "订单变更记录表")
-public class WechatStoreOrderChangeLog {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "订单ID")
-    @TableField("order_id")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    @TableField("order_no")
-    private String orderNo;
-
-    @ApiModelProperty(value = "批次号(同一时间点的操作使用同一批次号,用于分组展示)")
-    @TableField("batch_no")
-    private String batchNo;
-
-    @ApiModelProperty(value = "操作类型(1:首次下单, 3:更新订单)")
-    @TableField("operation_type")
-    private Integer operationType;
-
-    @ApiModelProperty(value = "菜品ID")
-    @TableField("cuisine_id")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    @TableField("cuisine_name")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品类型(1:单品, 2:套餐)")
-    @TableField("cuisine_type")
-    private Integer cuisineType;
-
-    @ApiModelProperty(value = "菜品图片")
-    @TableField("cuisine_image")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "单价")
-    @TableField("unit_price")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "数量变化(新增的数量,正数表示增加,负数表示减少)")
-    @TableField("quantity_change")
-    private Integer quantityChange;
-
-    @ApiModelProperty(value = "变化前数量(用于展示变化前后对比)")
-    @TableField("quantity_before")
-    private Integer quantityBefore;
-
-    @ApiModelProperty(value = "变化后数量(用于展示变化前后对比)")
-    @TableField("quantity_after")
-    private Integer quantityAfter;
-
-    @ApiModelProperty(value = "金额变化(新增的金额)")
-    @TableField("amount_change")
-    private BigDecimal amountChange;
-
-    @ApiModelProperty(value = "操作时间")
-    @TableField("operation_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date operationTime;
-
-    @ApiModelProperty(value = "操作人ID")
-    @TableField("operator_user_id")
-    private Integer operatorUserId;
-
-    @ApiModelProperty(value = "操作人手机号")
-    @TableField("operator_user_phone")
-    private String operatorUserPhone;
-
-    @ApiModelProperty(value = "备注")
-    @TableField("remark")
-    private String remark;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 108
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderDetail.java

@@ -1,108 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.math.BigDecimal;
-import java.util.Date;
-
-/**
- * 订单明细表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_order_detail")
-@ApiModel(value = "WechatStoreOrderDetail对象", description = "订单明细表")
-public class WechatStoreOrderDetail {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "订单ID")
-    @TableField("order_id")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "订单号")
-    @TableField("order_no")
-    private String orderNo;
-
-    @ApiModelProperty(value = "菜品ID")
-    @TableField("cuisine_id")
-    private Integer cuisineId;
-
-    @ApiModelProperty(value = "菜品名称")
-    @TableField("cuisine_name")
-    private String cuisineName;
-
-    @ApiModelProperty(value = "菜品类型(1:单品, 2:套餐)")
-    @TableField("cuisine_type")
-    private Integer cuisineType;
-
-    @ApiModelProperty(value = "菜品图片")
-    @TableField("cuisine_image")
-    private String cuisineImage;
-
-    @ApiModelProperty(value = "单价")
-    @TableField("unit_price")
-    private BigDecimal unitPrice;
-
-    @ApiModelProperty(value = "数量")
-    @TableField("quantity")
-    private Integer quantity;
-
-    @ApiModelProperty(value = "小计金额")
-    @TableField("subtotal_amount")
-    private BigDecimal subtotalAmount;
-
-    @ApiModelProperty(value = "添加该菜品的用户ID")
-    @TableField("add_user_id")
-    private Integer addUserId;
-
-    @ApiModelProperty(value = "添加该菜品的用户手机号")
-    @TableField("add_user_phone")
-    private String addUserPhone;
-
-    @ApiModelProperty(value = "是否加餐(0:初始下单, 1:加餐)")
-    @TableField("is_add_dish")
-    private Integer isAddDish;
-
-    @ApiModelProperty(value = "加餐时间")
-    @TableField("add_dish_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date addDishTime;
-
-    @ApiModelProperty(value = "备注")
-    @TableField("remark")
-    private String remark;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 76
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreOrderLock.java

@@ -1,76 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 订单锁定记录表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_order_lock")
-@ApiModel(value = "WechatStoreOrderLock对象", description = "订单锁定记录表")
-public class WechatStoreOrderLock {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "桌号ID(下单锁定)")
-    @TableField("table_id")
-    private Integer tableId;
-
-    @ApiModelProperty(value = "订单ID(结算锁定)")
-    @TableField("order_id")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "锁定类型(1:下单锁定, 2:结算锁定)")
-    @TableField("lock_type")
-    private Integer lockType;
-
-    @ApiModelProperty(value = "锁定用户ID")
-    @TableField("lock_user_id")
-    private Integer lockUserId;
-
-    @ApiModelProperty(value = "锁定用户手机号")
-    @TableField("lock_user_phone")
-    private String lockUserPhone;
-
-    @ApiModelProperty(value = "锁定过期时间")
-    @TableField("lock_expire_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date lockExpireTime;
-
-    @ApiModelProperty(value = "锁定状态(0:已释放, 1:锁定中)")
-    @TableField("lock_status")
-    private Integer lockStatus;
-
-    @ApiModelProperty(value = "释放时间")
-    @TableField("release_time")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date releaseTime;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-}

+ 0 - 177
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStorePaymentConfig.java

@@ -1,177 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-import shop.alien.util.typehandler.BlobByteArrayTypeHandler;
-
-import java.util.Date;
-
-/**
- * 支付配置表(支付宝等)
- *
- * @author system
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_payment_config")
-@ApiModel(value = "WechatStorePaymentConfig对象", description = "支付配置表")
-public class WechatStorePaymentConfig {
-
-    @ApiModelProperty(value = "主键")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "店铺ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "店铺用户id")
-    @TableField("store_user_id")
-    private Integer storeUserId;
-
-    @ApiModelProperty(value = "应用ID")
-    @TableField("app_id")
-    private String appId;
-
-    @ApiModelProperty(value = "应用私钥")
-    @TableField("app_secret_cert")
-    private String appSecretCert;
-
-    @ApiModelProperty(value = "应用公钥证书文件(存储文件内容)(支付宝)BLOB,原样存取不经过字符编码")
-    @TableField(value = "app_public_cert", typeHandler = BlobByteArrayTypeHandler.class)
-    private byte[] appPublicCert;
-
-    @ApiModelProperty(value = "应用公钥证书路径")
-    @TableField("app_public_cert_path")
-    private String appPublicCertPath;
-
-    @ApiModelProperty(value = "应用公钥证书文件名称")
-    @TableField("app_public_cert_name")
-    private String appPublicCertName;
-
-    @ApiModelProperty(value = "支付宝公钥证书文件(存储文件内容)(支付宝)BLOB,原样存取不经过字符编码")
-    @TableField(value = "alipay_public_cert", typeHandler = BlobByteArrayTypeHandler.class)
-    private byte[] alipayPublicCert;
-
-    @ApiModelProperty(value = "支付宝公钥证书路径")
-    @TableField("alipay_public_cert_path")
-    private String alipayPublicCertPath;
-
-    @ApiModelProperty(value = "支付宝公钥证书文件名称")
-    @TableField("alipay_public_cert_name")
-    private String alipayPublicCertName;
-
-    @ApiModelProperty(value = "支付宝根证书文件(存储文件内容)(支付宝)BLOB,原样存取不经过字符编码")
-    @TableField(value = "alipay_root_cert", typeHandler = BlobByteArrayTypeHandler.class)
-    private byte[] alipayRootCert;
-
-    @ApiModelProperty(value = "支付宝根证书路径")
-    @TableField("alipay_root_cert_path")
-    private String alipayRootCertPath;
-
-    @ApiModelProperty(value = "支付宝根证书文件名称")
-    @TableField("alipay_root_cert_name")
-    private String alipayRootCertName;
-
-    @ApiModelProperty(value = "微信appId")
-    @TableField("wechat_app_id")
-    private String wechatAppId;
-
-    @ApiModelProperty(value = "微信支付mini appId")
-    @TableField("wechat_mini_app_id")
-    private String wechatMiniAppId;
-
-    @ApiModelProperty(value = "微信mchId")
-    @TableField("wechat_mch_id")
-    private String wechatMchId;
-
-    @ApiModelProperty(value = "微信商户API证书序列号")
-    @TableField("merchant_serial_number")
-    private String merchantSerialNumber;
-
-    @ApiModelProperty(value = "微信商户的 APIv3 Key")
-    @TableField("api_v3_key")
-    private String apiV3Key;
-
-    @ApiModelProperty(value = "微信支付公钥ID")
-    @TableField("wechat_pay_public_key_id")
-    private String wechatPayPublicKeyId;
-
-    @ApiModelProperty(value = "微信私钥路径")
-    @TableField("wechat_private_key_path")
-    private String wechatPrivateKeyPath;
-
-    @ApiModelProperty(value = "微信私钥文件名")
-    @TableField("wechat_private_key_name")
-    private String wechatPrivateKeyName;
-
-    @ApiModelProperty(value = "微信私钥文件(存储文件内容)BLOB,原样存取不经过字符编码")
-    @TableField(value = "wechat_private_key_file", typeHandler = BlobByteArrayTypeHandler.class)
-    private byte[] wechatPrivateKeyFile;
-
-    @ApiModelProperty(value = "微信公钥路径")
-    @TableField("wechat_pay_public_key_file_path")
-    private String wechatPayPublicKeyFilePath;
-
-    @ApiModelProperty(value = "微信公钥文件名")
-    @TableField("wechat_pay_public_key_file_name")
-    private String wechatPayPublicKeyFileName;
-
-    @ApiModelProperty(value = "微信公钥文件(存储文件内容)BLOB,原样存取不经过字符编码")
-    @TableField(value = "wechat_pay_public_key_file", typeHandler = BlobByteArrayTypeHandler.class)
-    private byte[] wechatPayPublicKeyFile;
-
-    @ApiModelProperty(value = "收款银行卡号")
-    @TableField("bank_card_no")
-    private String bankCardNo;
-
-    @ApiModelProperty(value = "开户银行名称")
-    @TableField("bank_name")
-    private String bankName;
-
-    @ApiModelProperty(value = "商家微信 appid")
-    @TableField("store_wechat_id")
-    private String storeWechatId;
-
-    @ApiModelProperty(value = "商家微信名称")
-    @TableField("store_wechat_name")
-    private String storeWechatName;
-
-    @ApiModelProperty(value = "商家支付宝 appid")
-    @TableField("store_ali_id")
-    private String storeAliId;
-
-    @ApiModelProperty(value = "商家支付宝名称")
-    @TableField("store_ali_name")
-    private String storeAliName;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 98
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreTable.java

@@ -1,98 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 桌号表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_table")
-@ApiModel(value = "WechatStoreTable对象", description = "桌号表")
-public class WechatStoreTable {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "桌号")
-    @TableField("table_number")
-    private String tableNumber;
-
-    @ApiModelProperty(value = "分类ID(关联store_booking_category表)")
-    @TableField("category_id")
-    private Integer categoryId;
-
-    @ApiModelProperty(value = "座位数")
-    @TableField("seating_capacity")
-    private Integer seatingCapacity;
-
-    @ApiModelProperty(value = "当前进行中的订单ID(订单结账或取消后清空)")
-    @TableField("current_order_id")
-    private Integer currentOrderId;
-
-    @ApiModelProperty(value = "当前使用的优惠券ID")
-    @TableField("current_coupon_id")
-    private Integer currentCouponId;
-
-    @ApiModelProperty(value = "购物车商品数量(缓存)")
-    @TableField("cart_item_count")
-    private Integer cartItemCount;
-
-    @ApiModelProperty(value = "购物车总金额(缓存)")
-    @TableField("cart_total_amount")
-    private java.math.BigDecimal cartTotalAmount;
-
-    @ApiModelProperty(value = "二维码URL")
-    @TableField("qrcode_url")
-    private String qrcodeUrl;
-
-    @ApiModelProperty(value = "状态(0:空闲, 1:就餐中, 2:其他, 3:加餐)")
-    @TableField("status")
-    private Integer status;
-
-    @ApiModelProperty(value = "当前就餐人数(就餐中时由首客填写,后续用户共用)")
-    @TableField("diner_count")
-    private Integer dinerCount;
-
-    @ApiModelProperty(value = "备注")
-    @TableField("remark")
-    private String remark;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 78
alien-entity/src/main/java/shop/alien/entity/store/wechat/WechatStoreTableLog.java

@@ -1,78 +0,0 @@
-package shop.alien.entity.store.wechat;
-
-import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 桌号换桌记录表
- *
- * @author system
- * @since 2025-01-XX
- */
-@Data
-@JsonInclude
-@TableName("wechat_store_table_log")
-@ApiModel(value = "WechatStoreTableLog对象", description = "桌号换桌记录表")
-public class WechatStoreTableLog {
-
-    @ApiModelProperty(value = "主键ID")
-    @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
-
-    @ApiModelProperty(value = "门店ID")
-    @TableField("store_id")
-    private Integer storeId;
-
-    @ApiModelProperty(value = "订单ID")
-    @TableField("order_id")
-    private Integer orderId;
-
-    @ApiModelProperty(value = "原桌号ID")
-    @TableField("from_table_id")
-    private Integer fromTableId;
-
-    @ApiModelProperty(value = "原桌号")
-    @TableField("from_table_number")
-    private String fromTableNumber;
-
-    @ApiModelProperty(value = "目标桌号ID")
-    @TableField("to_table_id")
-    private Integer toTableId;
-
-    @ApiModelProperty(value = "目标桌号")
-    @TableField("to_table_number")
-    private String toTableNumber;
-
-    @ApiModelProperty(value = "换桌原因")
-    @TableField("change_reason")
-    private String changeReason;
-
-    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
-    @TableField("delete_flag")
-    @TableLogic
-    private Integer deleteFlag;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "created_time", fill = FieldFill.INSERT)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty(value = "创建人ID")
-    @TableField("created_user_id")
-    private Integer createdUserId;
-
-    @ApiModelProperty(value = "修改时间")
-    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date updatedTime;
-
-    @ApiModelProperty(value = "修改人ID")
-    @TableField("updated_user_id")
-    private Integer updatedUserId;
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCartMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreCart;
-
-/**
- * 小程序点餐专用表 WechatStoreCart Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreCartMapper extends BaseMapper<WechatStoreCart> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCouponUsageMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreCouponUsage;
-
-/**
- * 小程序点餐专用表 WechatStoreCouponUsage Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreCouponUsageMapper extends BaseMapper<WechatStoreCouponUsage> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineCategoryMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCategory;
-
-/**
- * 小程序点餐专用表 WechatStoreCuisineCategory Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreCuisineCategoryMapper extends BaseMapper<WechatStoreCuisineCategory> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineComboMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreCuisineCombo;
-
-/**
- * 小程序点餐专用表 WechatStoreCuisineCombo Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreCuisineComboMapper extends BaseMapper<WechatStoreCuisineCombo> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreCuisineMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreCuisine;
-
-/**
- * 小程序点餐专用表 WechatStoreCuisine Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreCuisineMapper extends BaseMapper<WechatStoreCuisine> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderChangeLogMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreOrderChangeLog;
-
-/**
- * 小程序点餐专用表 WechatStoreOrderChangeLog Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreOrderChangeLogMapper extends BaseMapper<WechatStoreOrderChangeLog> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderDetailMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreOrderDetail;
-
-/**
- * 小程序点餐专用表 WechatStoreOrderDetail Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreOrderDetailMapper extends BaseMapper<WechatStoreOrderDetail> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderLockMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreOrderLock;
-
-/**
- * 小程序点餐专用表 WechatStoreOrderLock Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreOrderLockMapper extends BaseMapper<WechatStoreOrderLock> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreOrderMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreOrder;
-
-/**
- * 小程序点餐专用表 WechatStoreOrder Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreOrderMapper extends BaseMapper<WechatStoreOrder> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStorePaymentConfigMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStorePaymentConfig;
-
-/**
- * 小程序点餐专用表 WechatStorePaymentConfig Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStorePaymentConfigMapper extends BaseMapper<WechatStorePaymentConfig> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreTableLogMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreTableLog;
-
-/**
- * 小程序点餐专用表 WechatStoreTableLog Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreTableLogMapper extends BaseMapper<WechatStoreTableLog> {
-}

+ 0 - 10
alien-entity/src/main/java/shop/alien/mapper/wechat/WechatStoreTableMapper.java

@@ -1,10 +0,0 @@
-package shop.alien.mapper.wechat;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import shop.alien.entity.store.wechat.WechatStoreTable;
-
-/**
- * 小程序点餐专用表 WechatStoreTable Mapper(与 APP 侧物理表隔离)
- */
-public interface WechatStoreTableMapper extends BaseMapper<WechatStoreTable> {
-}

+ 0 - 26
alien-store/src/main/java/shop/alien/store/annotation/OperationLog.java

@@ -1,26 +0,0 @@
-package shop.alien.store.annotation;
-
-import java.lang.annotation.*;
-
-/**
- * 操作日志注解
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface OperationLog {
-    /**
-     * 操作描述
-     */
-    String value() default "";
-
-    /**
-     * 操作类型
-     */
-    String type() default "";
-}
-

+ 0 - 22
alien-store/src/main/java/shop/alien/store/aspect/DiningOperationLogAspect.java

@@ -1,22 +0,0 @@
-package shop.alien.store.aspect;
-
-import lombok.extern.slf4j.Slf4j;
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.springframework.stereotype.Component;
-import shop.alien.store.annotation.OperationLog;
-
-/**
- * 点餐模块操作日志切面(与 store 全局 OperationLogAspect 区分 Bean 名)
- */
-@Slf4j
-@Aspect
-@Component
-public class DiningOperationLogAspect {
-
-    @Before("@annotation(operationLog)")
-    public void before(JoinPoint joinPoint, OperationLog operationLog) {
-        log.info("操作日志: {}", operationLog.value());
-    }
-}

+ 0 - 48
alien-store/src/main/java/shop/alien/store/controller/DiningCollectController.java

@@ -1,48 +0,0 @@
-package shop.alien.store.controller;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiOperationSupport;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiSort;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeCollect;
-import shop.alien.store.service.DiningCollectService;
-
-/**
- * 点餐模块-收藏控制器(Feign 调 store,供小程序使用)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/01/XX
- */
-@Slf4j
-@Api(tags = {"微信点餐-收藏(用户端)"})
-@ApiSort(4)
-@CrossOrigin
-@RestController
-@RequestMapping("/dining/collect")
-@RequiredArgsConstructor
-public class DiningCollectController {
-
-    private final DiningCollectService diningCollectService;
-
-    /**
-     * 添加收藏
-     */
-    @ApiOperation(value = "添加收藏", notes = "添加收藏,支持收藏店铺、商品等")
-    @ApiOperationSupport(order = 1)
-    @PostMapping("/addCollect")
-    public R<Boolean> addCollect(@ApiParam(value = "收藏对象", required = true) @RequestBody LifeCollect lifeCollect) {
-        log.info("DiningCollectController.addCollect?lifeCollect={}", lifeCollect);
-        try {
-            return diningCollectService.addCollect(lifeCollect);
-        } catch (Exception e) {
-            log.error("添加收藏失败: {}", e.getMessage(), e);
-            return R.fail("添加收藏失败: " + e.getMessage());
-        }
-    }
-}

+ 0 - 307
alien-store/src/main/java/shop/alien/store/controller/DiningController.java

@@ -1,307 +0,0 @@
-package shop.alien.store.controller;
-
-import io.swagger.annotations.*;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.vo.TableDiningStatusVO;
-import shop.alien.entity.store.vo.*;
-import shop.alien.store.service.DiningService;
-import shop.alien.store.util.TokenUtil;
-
-import java.util.List;
-
-/**
- * 点餐控制器
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Api(tags = {"小程序-点餐管理"})
-@CrossOrigin
-@RestController
-@RequestMapping("/store/dining")
-@RequiredArgsConstructor
-public class DiningController {
-
-    private final DiningService diningService;
-
-    @ApiOperation(value = "查询餐桌是否处于就餐中", notes = "免登录可调用,用于前端判断是否跳过选择用餐人数。就餐中(status=1)、加餐(status=3) 均视为就餐状态,且 diner_count 有值 时 inDining=true")
-    @GetMapping("/table-dining-status")
-    public R<TableDiningStatusVO> getTableDiningStatus(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.getTableDiningStatus?tableId={}", tableId);
-        try {
-            TableDiningStatusVO vo = diningService.getTableDiningStatus(tableId);
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("查询餐桌就餐状态失败: {}", e.getMessage(), e);
-            return R.fail("查询餐桌就餐状态失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "获取点餐页面信息", notes = "首客选桌时传就餐人数,餐桌置为就餐中并保存人数;后续用户选同一桌可不传就餐人数,将使用表中已保存人数")
-    @GetMapping("/page-info")
-    public R<DiningPageInfoVO> getDiningPageInfo(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "就餐人数(首客必传;餐桌已就餐中时可省略,将使用已保存人数)") @RequestParam(required = false) Integer dinerCount) {
-        log.info("DiningController.getDiningPageInfo?tableId={}, dinerCount={}", tableId, dinerCount);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            DiningPageInfoVO vo = diningService.getDiningPageInfo(tableId, dinerCount);
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("获取点餐页面信息失败: {}", e.getMessage(), e);
-            return R.fail("获取点餐页面信息失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "搜索菜品", notes = "模糊搜索菜品,关键词限10字")
-    @GetMapping("/search")
-    public R<List<CuisineListVO>> searchCuisines(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
-            @ApiParam(value = "搜索关键词", required = false) @RequestParam(required = false) String keyword,
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.searchCuisines?storeId={}, keyword={}, tableId={}", storeId, keyword, tableId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            // 限制关键词长度
-            if (StringUtils.hasText(keyword) && keyword.length() > 10) {
-                keyword = keyword.substring(0, 10);
-            }
-            List<CuisineListVO> list = diningService.searchCuisines(storeId, keyword, tableId);
-            return R.data(list);
-        } catch (Exception e) {
-            log.error("搜索菜品失败: {}", e.getMessage(), e);
-            return R.fail("搜索菜品失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "根据分类获取菜品列表", notes = "分页获取菜品列表,默认每页12条")
-    @GetMapping("/cuisines")
-    public R<List<CuisineListVO>> getCuisinesByCategory(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
-            @ApiParam(value = "分类ID", required = false) @RequestParam(required = false) Integer categoryId,
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "页码", required = false) @RequestParam(defaultValue = "1") Integer page,
-            @ApiParam(value = "每页数量", required = false) @RequestParam(defaultValue = "12") Integer size) {
-        log.info("DiningController.getCuisinesByCategory?storeId={}, categoryId={}, tableId={}, page={}, size={}", storeId, categoryId, tableId, page, size);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            List<CuisineListVO> list = diningService.getCuisinesByCategory(storeId, categoryId, tableId, page, size);
-            return R.data(list);
-        } catch (Exception e) {
-            log.error("获取菜品列表失败: {}", e.getMessage(), e);
-            return R.fail("获取菜品列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "获取菜品详情", notes = "获取菜品详细信息,包含图片列表、月售数量等")
-    @GetMapping("/cuisine/{cuisineId}")
-    public R<CuisineDetailVO> getCuisineDetail(
-            @ApiParam(value = "菜品ID", required = true) @PathVariable Integer cuisineId,
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.getCuisineDetail?cuisineId={}, tableId={}", cuisineId, tableId);
-        try {
-            CuisineDetailVO vo = diningService.getCuisineDetail(cuisineId, tableId);
-            
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("获取菜品详情失败: {}", e.getMessage(), e);
-            return R.fail("获取菜品详情失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "获取可领取的优惠券列表", notes = "获取用户可领取的优惠券")
-    @GetMapping("/coupons/available")
-    public R<List<AvailableCouponVO>> getAvailableCoupons(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
-        log.info("DiningController.getAvailableCoupons?storeId={}", storeId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            List<AvailableCouponVO> list = diningService.getAvailableCoupons(storeId, userId);
-            return R.data(list);
-        } catch (Exception e) {
-            log.error("获取可领取优惠券列表失败: {}", e.getMessage(), e);
-            return R.fail("获取可领取优惠券列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "领取优惠券", notes = "用户领取优惠券")
-    @PostMapping("/coupon/receive")
-    public R<Boolean> receiveCoupon(
-            @ApiParam(value = "优惠券ID", required = true) @RequestParam Integer couponId) {
-        log.info("DiningController.receiveCoupon?couponId={}", couponId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = diningService.receiveCoupon(couponId, userId);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("领取优惠券失败: {}", e.getMessage(), e);
-            return R.fail("领取优惠券失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "获取订单确认页面信息", notes = "获取订单确认页面的所有信息")
-    @GetMapping("/order/confirm")
-    public R<OrderConfirmVO> getOrderConfirmInfo(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "就餐人数", required = true) @RequestParam Integer dinerCount) {
-        log.info("DiningController.getOrderConfirmInfo?tableId={}, dinerCount={}", tableId, dinerCount);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            OrderConfirmVO vo = diningService.getOrderConfirmInfo(tableId, dinerCount, userId);
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("获取订单确认页面信息失败: {}", e.getMessage(), e);
-            return R.fail("获取订单确认页面信息失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "锁定订单", notes = "锁定订单,防止多人同时下单")
-    @PostMapping("/order/lock")
-    public R<Boolean> lockOrder(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.lockOrder?tableId={}", tableId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = diningService.lockOrder(tableId, userId);
-            if (!result) {
-                return R.fail("订单已被其他用户锁定,无法下单");
-            }
-            return R.data(true);
-        } catch (Exception e) {
-            log.error("锁定订单失败: {}", e.getMessage(), e);
-            return R.fail("锁定订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "解锁订单", notes = "解锁订单")
-    @PostMapping("/order/unlock")
-    public R<Boolean> unlockOrder(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.unlockOrder?tableId={}", tableId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            diningService.unlockOrder(tableId, userId);
-            return R.data(true);
-        } catch (Exception e) {
-            log.error("解锁订单失败: {}", e.getMessage(), e);
-            return R.fail("解锁订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "检查订单锁定状态", notes = "检查订单是否被锁定")
-    @GetMapping("/order/check-lock")
-    public R<Integer> checkOrderLock(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("DiningController.checkOrderLock?tableId={}", tableId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            Integer lockUserId = diningService.checkOrderLock(tableId);
-            return R.data(lockUserId);
-        } catch (Exception e) {
-            log.error("检查订单锁定状态失败: {}", e.getMessage(), e);
-            return R.fail("检查订单锁定状态失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "获取订单结算确认页面信息", notes = "获取订单结算确认页面的所有信息")
-    @GetMapping("/order/settlement")
-    public R<shop.alien.entity.store.vo.OrderSettlementVO> getOrderSettlementInfo(
-            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
-        log.info("DiningController.getOrderSettlementInfo?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            shop.alien.entity.store.vo.OrderSettlementVO vo = diningService.getOrderSettlementInfo(orderId, userId);
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("获取订单结算确认页面信息失败: {}", e.getMessage(), e);
-            return R.fail("获取订单结算确认页面信息失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "锁定订单结算", notes = "锁定订单结算,防止多人同时结算")
-    @PostMapping("/order/settlement/lock")
-    public R<Boolean> lockSettlement(
-            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
-        log.info("DiningController.lockSettlement?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = diningService.lockSettlement(orderId, userId);
-            if (!result) {
-                return R.fail("订单已被其他用户锁定,无法结算");
-            }
-            return R.data(true);
-        } catch (Exception e) {
-            log.error("锁定订单结算失败: {}", e.getMessage(), e);
-            return R.fail("锁定订单结算失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "解锁订单结算", notes = "解锁订单结算")
-    @PostMapping("/order/settlement/unlock")
-    public R<Boolean> unlockSettlement(
-            @ApiParam(value = "订单ID", required = true) @RequestParam Integer orderId) {
-        log.info("DiningController.unlockSettlement?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            diningService.unlockSettlement(orderId, userId);
-            return R.data(true);
-        } catch (Exception e) {
-            log.error("解锁订单结算失败: {}", e.getMessage(), e);
-            return R.fail("解锁订单结算失败: " + e.getMessage());
-        }
-    }
-}

+ 0 - 188
alien-store/src/main/java/shop/alien/store/controller/DiningCouponController.java

@@ -1,188 +0,0 @@
-package shop.alien.store.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiOperationSupport;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiSort;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.vo.LifeDiscountCouponVo;
-import shop.alien.store.service.DiningCouponService;
-
-import javax.servlet.http.HttpServletRequest;
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 点餐模块-优惠券控制器(Feign 调 store,供小程序:我的优惠券/详情/选券)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/1/29
- */
-@Slf4j
-@Api(tags = {"微信点餐-优惠券(用户端)"})
-@ApiSort(3)
-@CrossOrigin
-@RestController
-@RequestMapping({"/dining/coupon"})
-@RequiredArgsConstructor
-public class DiningCouponController {
-
-    private final DiningCouponService diningCouponService;
-
-    /**
-     * 获取该用户所有的优惠券列表
-     */
-    @ApiOperation("获取该用户所有的优惠券列表。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
-    @ApiOperationSupport(order = 9)
-    @GetMapping("/getUserCouponList")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = false),
-            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = false),
-            @ApiImplicitParam(name = "tabType", value = "分页类型(0:全部(未使用),1:即将过期,2:已使用,3:已过期)", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "type", value = "券类型(不传:优惠券+代金券都返回,1:仅优惠券查 life_discount_coupon,4:仅代金券查 life_coupon)", dataType = "Integer", paramType = "query", required = false),
-            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选,仅当type不为4时有效)", dataType = "Integer", paramType = "query", required = false),
-            @ApiImplicitParam(name = "storeId", value = "商铺ID,可为空,传则仅返回该商铺的优惠券", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "storeName", value = "商铺名称模糊查询,可为空", dataType = "String", paramType = "query", required = false)
-    })
-    public R<List<LifeDiscountCouponVo>> getUserCouponList(
-            HttpServletRequest request,
-            @RequestParam(value = "page", defaultValue = "1") int page,
-            @RequestParam(value = "size", defaultValue = "10") int size,
-            @RequestParam("tabType") String tabType,
-            @RequestParam(value = "type", required = false) Integer type,
-            @RequestParam(value = "couponType", required = false) Integer couponType,
-            @RequestParam(value = "storeId", required = false) String storeId,
-            @RequestParam(value = "storeName", required = false) String storeName) {
-        log.info("DiningCouponController.getUserCouponList?page={}, size={}, tabType={}, type={}, couponType={}, storeId={}, storeName={}", page, size, tabType, type, couponType, storeId, storeName);
-        String authorization = request.getHeader("Authorization");
-        return diningCouponService.getUserCouponList(authorization, page, size, tabType, type, couponType, storeId, storeName);
-    }
-
-    /**
-     * 根据优惠券 id 获取优惠券详情(规则、门槛等)
-     */
-    @ApiOperation(value = "获取优惠券详情", notes = "需登录,请求头带 Authorization。counponId 与 store 接口拼写一致")
-    @GetMapping("/detail")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "counponId", value = "优惠券id", dataType = "String", paramType = "query", required = true)
-    })
-    public R<LifeDiscountCouponVo> getCounponDetailById(
-            HttpServletRequest request,
-            @RequestParam("counponId") String counponId) {
-        log.info("DiningCouponController.getCounponDetailById?counponId={}", counponId);
-        String authorization = request.getHeader("Authorization");
-        return diningCouponService.getCounponDetailById(authorization, counponId);
-    }
-
-    /**
-     * 获取该门店下用户可用/不可用优惠券列表(用于购物车/下单选券,按金额区分)
-     */
-    @ApiOperation(value = "获取门店可用优惠券列表", notes = "需登录。按 storeId+amount 返回可用券与不可用券及原因(满减门槛等)。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
-    @GetMapping("/storeUsableList")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "amount", value = "当前消费金额(满减门槛)", dataType = "BigDecimal", paramType = "query", required = true),
-            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)", dataType = "Integer", paramType = "query", required = false)
-    })
-    public R<Map<String, Object>> getStoreUserUsableCouponList(
-            HttpServletRequest request,
-            @RequestParam("storeId") String storeId,
-            @RequestParam("amount") BigDecimal amount,
-            @ApiParam(value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券") @RequestParam(value = "couponType", required = false) Integer couponType) {
-        log.info("DiningCouponController.getStoreUserUsableCouponList?storeId={}, amount={}, couponType={}", storeId, amount, couponType);
-        String authorization = request.getHeader("Authorization");
-        return diningCouponService.getStoreUserUsableCouponList(authorization, storeId, amount, couponType);
-    }
-
-    /**
-     * 查询用户拥有的优惠券(按符合支付条件优先,其次优惠力度大的优先)
-     */
-    @ApiOperation(value = "查询用户拥有的优惠券", notes = "需登录。查询用户拥有的优惠券,排序:符合支付条件的优先,其次优惠力度大的优先")
-    @GetMapping("/userOwned")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "门店ID(可选,如果提供则只查询该门店的优惠券)", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "amount", value = "当前消费金额(用于判断是否符合支付条件)", dataType = "BigDecimal", paramType = "query", required = false)
-    })
-    public R<List<LifeDiscountCouponVo>> getUserOwnedCoupons(
-            @ApiParam(value = "门店ID(可选)") @RequestParam(required = false) String storeId,
-            @ApiParam(value = "当前消费金额(可选,用于判断是否符合支付条件)") @RequestParam(required = false) BigDecimal amount) {
-        log.info("DiningCouponController.getUserOwnedCoupons?storeId={}, amount={}", storeId, amount);
-        return diningCouponService.getUserOwnedCoupons(storeId, amount);
-    }
-
-    /**
-     * 获取该用户该店铺优惠券列表
-     */
-    @ApiOperation(value = "获取该用户该店铺优惠券列表", notes = "需登录,请求头带 Authorization。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
-    @ApiOperationSupport(order = 7)
-    @GetMapping("/getStoreUserCouponList")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "商户id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)", dataType = "Integer", paramType = "query", required = false)
-    })
-    public R<List<LifeDiscountCouponVo>> getStoreUserCouponList(
-            HttpServletRequest request,
-            @ApiParam(value = "商户id", required = true) @RequestParam("storeId") String storeId,
-            @ApiParam(value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券") @RequestParam(value = "couponType", required = false) Integer couponType) {
-        log.info("DiningCouponController.getStoreUserCouponList?storeId={}, couponType={}", storeId, couponType);
-        String authorization = request.getHeader("Authorization");
-        return diningCouponService.getStoreUserCouponList(authorization, storeId, couponType);
-    }
-
-    /**
-     * 查询用户目前所拥有的优惠券(可通过商铺ID进行查询)
-     */
-    @ApiOperation(value = "查询用户目前所拥有的优惠券", notes = "需登录。查询用户目前所拥有的优惠券(未使用且未过期),可通过商铺ID进行筛选。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券")
-    @ApiOperationSupport(order = 8)
-    @GetMapping("/userOwnedByStore")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "商铺ID(可选,如果提供则只查询该商铺的优惠券)", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)", dataType = "Integer", paramType = "query", required = false)
-    })
-    public R<List<LifeDiscountCouponVo>> getUserOwnedCouponsByStore(
-            @ApiParam(value = "商铺ID(可选)") @RequestParam(required = false) String storeId,
-            @ApiParam(value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券") @RequestParam(value = "couponType", required = false) Integer couponType) {
-        log.info("DiningCouponController.getUserOwnedCouponsByStore?storeId={}, couponType={}", storeId, couponType);
-        return diningCouponService.getUserOwnedCouponsByStore(storeId, couponType);
-    }
-
-    /**
-     * 获取该店铺所有优惠券(分页), 好友优惠券
-     */
-    @ApiOperation(value = "获取该店铺所有优惠券(分页)", notes = "需登录,请求头带 Authorization。couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券。tab: 0:全部,1:进行中,2:已结束,3:草稿,4:未开始,5:已下架,6:已清库")
-    @ApiOperationSupport(order = 10)
-    @GetMapping("/getStoreAllCouponList")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "页码", dataType = "int", paramType = "query", required = false),
-            @ApiImplicitParam(name = "size", value = "每页条数", dataType = "int", paramType = "query", required = false),
-            @ApiImplicitParam(name = "storeId", value = "商户id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "couponName", value = "优惠券名称", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "tab", value = "分页类型(0:全部,1:进行中,2:已结束,3:草稿,4:未开始,5:已下架,6:已清库)", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "couponsFromType", value = "查询类型(1:我的优惠券,2:好友的优惠券)", dataType = "int", paramType = "query", required = false),
-            @ApiImplicitParam(name = "couponStatus", value = "优惠券状态(0:草稿,1:正式)", dataType = "int", paramType = "query", required = false),
-            @ApiImplicitParam(name = "couponType", value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)", dataType = "Integer", paramType = "query", required = false)
-    })
-    public R<IPage<LifeDiscountCouponVo>> getStoreAllCouponList(
-            HttpServletRequest request,
-            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(value = "page", defaultValue = "1") int page,
-            @ApiParam(value = "每页条数", defaultValue = "10") @RequestParam(value = "size", defaultValue = "10") int size,
-            @ApiParam(value = "商户id", required = true) @RequestParam("storeId") String storeId,
-            @ApiParam(value = "优惠券名称") @RequestParam(value = "couponName", required = false) String couponName,
-            @ApiParam(value = "分页类型(0:全部,1:进行中,2:已结束,3:草稿,4:未开始,5:已下架,6:已清库)", required = true) @RequestParam("tab") String tab,
-            @ApiParam(value = "查询类型(1:我的优惠券,2:好友的优惠券)", defaultValue = "1") @RequestParam(value = "couponsFromType", defaultValue = "1") int couponsFromType,
-            @ApiParam(value = "优惠券状态(0:草稿,1:正式)", defaultValue = "1") @RequestParam(value = "couponStatus", defaultValue = "1", required = false) int couponStatus,
-            @ApiParam(value = "优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券") @RequestParam(value = "couponType", required = false) Integer couponType) {
-        log.info("DiningCouponController.getStoreAllCouponList?page={}, size={}, storeId={}, couponName={}, tab={}, couponsFromType={}, couponStatus={}, couponType={}", page, size, storeId, couponName, tab, couponsFromType, couponStatus, couponType);
-        String authorization = request.getHeader("Authorization");
-        return diningCouponService.getStoreAllCouponList(authorization, page, size, storeId, couponName, tab, couponsFromType, couponStatus, couponType);
-    }
-}

+ 0 - 60
alien-store/src/main/java/shop/alien/store/controller/DiningFileUploadController.java

@@ -1,60 +0,0 @@
-package shop.alien.store.controller;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiOperationSupport;
-import io.swagger.annotations.ApiSort;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-import shop.alien.entity.result.R;
-import shop.alien.store.feign.AlienStoreFeign;
-
-/**
- * 点餐模块-文件上传控制器
- *
- * @author ssk
- * @version 1.0
- * @date 2025/01/XX
- */
-@Slf4j
-@Api(tags = {"小程序-文件上传"})
-@ApiSort(10)
-@CrossOrigin
-@RestController
-@RequestMapping("/dining/file")
-@RequiredArgsConstructor
-public class DiningFileUploadController {
-
-    private final AlienStoreFeign alienStoreFeign;
-
-    /**
-     * 上传图片到OSS(单个文件上传,支持图片、视频或PDF)
-     *
-     * @param file 文件对象
-     * @return R.data 为文件路径(String)
-     */
-    @ApiOperation(value = "上传图片到OSS", notes = "支持图片、视频或PDF文件上传,返回OSS文件路径")
-    @ApiOperationSupport(order = 1)
-    @PostMapping("/upload")
-    public R<String> upload(@RequestParam("file") MultipartFile file) {
-        log.info("DiningFileUploadController.upload?fileName={}", file != null ? file.getOriginalFilename() : null);
-        try {
-            if (file == null || file.isEmpty()) {
-                return R.fail("文件不能为空");
-            }
-            R<String> result = alienStoreFeign.uploadFile(file);
-            if (result.isSuccess()) {
-                log.info("文件上传成功,OSS路径:{}", result.getData());
-                return result;
-            } else {
-                log.error("文件上传失败:{}", result.getMsg());
-                return R.fail("文件上传失败:" + result.getMsg());
-            }
-        } catch (Exception e) {
-            log.error("文件上传异常:{}", e.getMessage(), e);
-            return R.fail("文件上传异常:" + e.getMessage());
-        }
-    }
-}

+ 57 - 59
alien-store/src/main/java/shop/alien/store/controller/DiningServiceController.java

@@ -9,19 +9,22 @@ import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreOrder;
 import shop.alien.entity.store.StoreTable;
 import shop.alien.entity.store.dto.CartDTO;
 import shop.alien.entity.store.dto.ChangeTableDTO;
 import shop.alien.entity.store.vo.*;
-import shop.alien.store.service.StoreOrderService;
-import shop.alien.store.util.TokenUtil;
+import shop.alien.store.feign.DiningServiceFeign;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 
 /**
- * APP 点餐聚合接口(原通过 Feign 调用 alien-dining,现与本模块 controller/service 同目录)。
+ * 点餐服务 Controller
+ * 供前端调用 alien-dining 模块的接口
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/01/XX
  */
 @Slf4j
 @Api(tags = {"点餐服务接口"})
@@ -32,13 +35,11 @@ import java.util.List;
 @RequiredArgsConstructor
 public class DiningServiceController {
 
-    private final DiningController diningController;
-    private final StoreOrderController storeOrderController;
-    private final StoreInfoController storeInfoController;
-    private final DiningUserController diningUserController;
-    private final DiningFileUploadController diningFileUploadController;
-    private final StoreOrderService storeOrderService;
+    private final DiningServiceFeign diningServiceFeign;
 
+    /**
+     * 从请求头获取 Authorization token
+     */
     private String getAuthorization(HttpServletRequest request) {
         String authorization = request.getHeader("Authorization");
         if (authorization == null || authorization.isEmpty()) {
@@ -47,6 +48,8 @@ public class DiningServiceController {
         return authorization;
     }
 
+    // ==================== 点餐相关接口 ====================
+
     @ApiOperation(value = "查询餐桌是否处于就餐中", notes = "免登录可调用,返回 inDining、dinerCount,供前端判断是否跳过选择用餐人数")
     @ApiOperationSupport(order = 0)
     @GetMapping("/table-dining-status")
@@ -54,7 +57,7 @@ public class DiningServiceController {
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
         try {
             log.info("查询餐桌就餐状态: tableId={}", tableId);
-            return diningController.getTableDiningStatus(tableId);
+            return diningServiceFeign.getTableDiningStatus(tableId);
         } catch (Exception e) {
             log.error("查询餐桌就餐状态失败: {}", e.getMessage(), e);
             return R.fail("查询餐桌就餐状态失败: " + e.getMessage());
@@ -69,9 +72,9 @@ public class DiningServiceController {
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
             @ApiParam(value = "就餐人数(首客必传;餐桌已就餐中时可省略)") @RequestParam(required = false) Integer dinerCount) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取点餐页面信息: tableId={}, dinerCount={}", tableId, dinerCount);
-            return diningController.getDiningPageInfo(tableId, dinerCount);
+            return diningServiceFeign.getDiningPageInfo(authorization, tableId, dinerCount);
         } catch (Exception e) {
             log.error("获取点餐页面信息失败: {}", e.getMessage(), e);
             return R.fail("获取点餐页面信息失败: " + e.getMessage());
@@ -87,9 +90,9 @@ public class DiningServiceController {
             @ApiParam(value = "搜索关键词", required = true) @RequestParam String keyword,
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("搜索菜品: storeId={}, keyword={}, tableId={}", storeId, keyword, tableId);
-            return diningController.searchCuisines(storeId, keyword, tableId);
+            return diningServiceFeign.searchCuisines(authorization, storeId, keyword, tableId);
         } catch (Exception e) {
             log.error("搜索菜品失败: {}", e.getMessage(), e);
             return R.fail("搜索菜品失败: " + e.getMessage());
@@ -104,13 +107,13 @@ public class DiningServiceController {
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
             @ApiParam(value = "分类ID(可为空,查询所有)") @RequestParam(required = false) Integer categoryId,
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer pageParam,
-            @ApiParam(value = "每页数量", defaultValue = "12") @RequestParam(defaultValue = "12") Integer sizeParam) {
+            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer page,
+            @ApiParam(value = "每页数量", defaultValue = "12") @RequestParam(defaultValue = "12") Integer size) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("根据分类获取菜品列表: storeId={}, categoryId={}, tableId={}, page={}, size={}",
-                    storeId, categoryId, tableId, pageParam, sizeParam);
-            return diningController.getCuisinesByCategory(storeId, categoryId, tableId, pageParam, sizeParam);
+                    storeId, categoryId, tableId, page, size);
+            return diningServiceFeign.getCuisinesByCategory(authorization, storeId, categoryId, tableId, page, size);
         } catch (Exception e) {
             log.error("根据分类获取菜品列表失败: {}", e.getMessage(), e);
             return R.fail("根据分类获取菜品列表失败: " + e.getMessage());
@@ -125,9 +128,9 @@ public class DiningServiceController {
             @ApiParam(value = "菜品ID", required = true) @PathVariable Integer cuisineId,
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取菜品详情: cuisineId={}, tableId={}", cuisineId, tableId);
-            return diningController.getCuisineDetail(cuisineId, tableId);
+            return diningServiceFeign.getCuisineDetail(authorization, cuisineId, tableId);
         } catch (Exception e) {
             log.error("获取菜品详情失败: {}", e.getMessage(), e);
             return R.fail("获取菜品详情失败: " + e.getMessage());
@@ -141,15 +144,17 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取可领取的优惠券列表: storeId={}", storeId);
-            return diningController.getAvailableCoupons(storeId);
+            return diningServiceFeign.getAvailableCoupons(authorization, storeId);
         } catch (Exception e) {
             log.error("获取可领取的优惠券列表失败: {}", e.getMessage(), e);
             return R.fail("获取可领取的优惠券列表失败: " + e.getMessage());
         }
     }
 
+    // ==================== 订单相关接口 ====================
+
     @ApiOperation(value = "获取购物车", notes = "根据桌号ID获取购物车信息")
     @ApiOperationSupport(order = 6)
     @GetMapping("/order/cart/{tableId}")
@@ -157,9 +162,9 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取购物车: tableId={}", tableId);
-            return storeOrderController.getCart(tableId);
+            return diningServiceFeign.getCart(authorization, tableId);
         } catch (Exception e) {
             log.error("获取购物车失败: {}", e.getMessage(), e);
             return R.fail("获取购物车失败: " + e.getMessage());
@@ -173,9 +178,9 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "换桌参数(原桌号ID、目标桌号ID、换桌原因)", required = true) @RequestBody ChangeTableDTO dto) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("换桌: fromTableId={}, toTableId={}, changeReason={}", dto.getFromTableId(), dto.getToTableId(), dto.getChangeReason());
-            return storeOrderController.changeTable(dto);
+            return diningServiceFeign.changeTable(authorization, dto);
         } catch (Exception e) {
             log.error("换桌失败: {}", e.getMessage(), e);
             return R.fail("换桌失败: " + e.getMessage());
@@ -189,9 +194,9 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取订单详情: orderId={}", orderId);
-            return storeOrderController.getOrderDetail(orderId);
+            return diningServiceFeign.getOrderDetail(authorization, orderId);
         } catch (Exception e) {
             log.error("获取订单详情失败: {}", e.getMessage(), e);
             return R.fail("获取订单详情失败: " + e.getMessage());
@@ -207,15 +212,9 @@ public class DiningServiceController {
             @ApiParam(value = "每页数量", defaultValue = "10") @RequestParam(defaultValue = "10") Integer size,
             @ApiParam(value = "订单状态(可选)") @RequestParam(required = false) Integer status) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取订单列表: page={}, size={}, status={}", page, size, status);
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            Page<StoreOrder> p = new Page<>(page, size);
-            IPage<StoreOrderPageVO> data = storeOrderService.getOrderPageWithCuisines(p, null, null, status, null);
-            return R.data(data);
+            return diningServiceFeign.getOrderList(authorization, page, size, status);
         } catch (Exception e) {
             log.error("获取订单列表失败: {}", e.getMessage(), e);
             return R.fail("获取订单列表失败: " + e.getMessage());
@@ -234,10 +233,12 @@ public class DiningServiceController {
             @ApiParam(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)") @RequestParam(required = false) Integer orderStatus,
             @ApiParam(value = "搜索关键词(订单编号或菜品名称,限15字)") @RequestParam(required = false) String keyword) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("分页查询订单列表: current={}, size={}, storeId={}, tableId={}, orderStatus={}, keyword={}",
                     current, size, storeId, tableId, orderStatus, keyword);
-            return storeOrderController.getOrderPage(current, size, storeId, tableId, orderStatus, keyword);
+            R<Page<StoreOrderPageVO>> result = diningServiceFeign.getOrderPage(authorization, current, size, storeId, tableId, orderStatus, keyword);
+            // 将 Page 转换为 IPage 返回(Page 实现了 IPage 接口,可以直接返回)
+            return R.data(result.getData());
         } catch (Exception e) {
             log.error("分页查询订单列表失败: {}", e.getMessage(), e);
             return R.fail("分页查询订单列表失败: " + e.getMessage());
@@ -251,9 +252,9 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("查询订单变更记录: orderId={}", orderId);
-            return storeOrderController.getOrderChangeLogs(orderId);
+            return diningServiceFeign.getOrderChangeLogs(authorization, orderId);
         } catch (Exception e) {
             log.error("查询订单变更记录失败: {}", e.getMessage(), e);
             return R.fail("查询订单变更记录失败: " + e.getMessage());
@@ -267,38 +268,33 @@ public class DiningServiceController {
             HttpServletRequest request,
             @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("商家手动完成订单: orderId={}", orderId);
-            return storeOrderController.completeOrderByMerchant(orderId);
+            return diningServiceFeign.completeOrderByMerchant(authorization, orderId);
         } catch (Exception e) {
             log.error("商家手动完成订单失败: {}", e.getMessage(), e);
             return R.fail("商家手动完成订单失败: " + e.getMessage());
         }
     }
 
+    // ==================== 用户相关接口 ====================
+
     @ApiOperation(value = "获取用户信息", notes = "获取当前登录用户的详细信息(从token中获取用户ID)")
     @ApiOperationSupport(order = 9)
     @GetMapping("/user/info")
     public R<Object> getUserInfo(HttpServletRequest request) {
         try {
-            getAuthorization(request);
+            String authorization = getAuthorization(request);
             log.info("获取用户信息");
-            R<?> inner = diningUserController.getUserInfo();
-            if (inner == null) {
-                return R.fail("获取用户信息失败");
-            }
-            if (!inner.isSuccess()) {
-                return R.fail(inner.getMsg());
-            }
-            @SuppressWarnings("unchecked")
-            R<Object> out = (R<Object>) (R<?>) inner;
-            return out;
+            return diningServiceFeign.getUserInfo(authorization);
         } catch (Exception e) {
             log.error("获取用户信息失败: {}", e.getMessage(), e);
             return R.fail("获取用户信息失败: " + e.getMessage());
         }
     }
 
+    // ==================== 门店信息接口 ====================
+
     @ApiOperation(value = "根据门店ID查询桌号列表", notes = "查询指定门店下的所有桌号")
     @ApiOperationSupport(order = 10)
     @GetMapping("/store/tables")
@@ -306,7 +302,7 @@ public class DiningServiceController {
             @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
         try {
             log.info("根据门店ID查询桌号列表: storeId={}", storeId);
-            return storeInfoController.getTablesByStoreId(storeId);
+            return diningServiceFeign.getTablesByStoreId(storeId);
         } catch (Exception e) {
             log.error("根据门店ID查询桌号列表失败: {}", e.getMessage(), e);
             return R.fail("根据门店ID查询桌号列表失败: " + e.getMessage());
@@ -321,7 +317,7 @@ public class DiningServiceController {
             @ApiParam(value = "菜品名称模糊查询关键词(可选)") @RequestParam(required = false) String keyword) {
         try {
             log.info("根据门店ID查询菜品种类及菜品: storeId={}, keyword={}", storeId, keyword);
-            return storeInfoController.getCategoriesWithCuisinesByStoreId(storeId, keyword);
+            return diningServiceFeign.getCategoriesWithCuisinesByStoreId(storeId, keyword);
         } catch (Exception e) {
             log.error("查询菜品种类及菜品失败: {}", e.getMessage(), e);
             return R.fail("查询菜品种类及菜品失败: " + e.getMessage());
@@ -335,13 +331,15 @@ public class DiningServiceController {
             @ApiParam(value = "菜品种类ID", required = true) @PathVariable Integer categoryId) {
         try {
             log.info("删除菜品种类: categoryId={}", categoryId);
-            return storeInfoController.deleteCategory(categoryId);
+            return diningServiceFeign.deleteCategory(categoryId);
         } catch (Exception e) {
             log.error("删除菜品种类失败: {}", e.getMessage(), e);
             return R.fail("删除菜品种类失败: " + e.getMessage());
         }
     }
 
+    // ==================== 文件上传接口 ====================
+
     @ApiOperation(value = "上传图片到OSS", notes = "支持图片、视频或PDF文件上传,返回OSS文件路径")
     @ApiOperationSupport(order = 11)
     @PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@@ -352,7 +350,7 @@ public class DiningServiceController {
                 return R.fail("文件不能为空");
             }
             log.info("上传文件: fileName={}, size={}", file.getOriginalFilename(), file.getSize());
-            return diningFileUploadController.upload(file);
+            return diningServiceFeign.uploadFile(file);
         } catch (Exception e) {
             log.error("上传文件失败: {}", e.getMessage(), e);
             return R.fail("上传文件失败: " + e.getMessage());

+ 0 - 188
alien-store/src/main/java/shop/alien/store/controller/DiningUserController.java

@@ -1,188 +0,0 @@
-package shop.alien.store.controller;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiSort;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.result.R;
-import shop.alien.store.dto.ChangePhoneDto;
-import shop.alien.store.dto.UserProfileUpdateDto;
-import shop.alien.store.dto.VerifyTokenDto;
-import shop.alien.store.dto.WeChatLoginDto;
-import shop.alien.store.service.DiningUserService;
-import shop.alien.store.util.TokenUtil;
-import shop.alien.store.vo.DiningUserVo;
-import shop.alien.store.vo.TokenVerifyVo;
-import org.apache.commons.lang3.StringUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.validation.Valid;
-
-/**
- * 点餐用户控制器
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Slf4j
-@Api(tags = {"微信点餐-登录(用户端)"})
-@ApiSort(2)
-@CrossOrigin
-@RestController
-@RequestMapping("/dining/user")
-@RequiredArgsConstructor
-public class DiningUserController {
-
-    private final DiningUserService diningUserService;
-
-    @ApiOperation(value = "微信小程序登录", notes = "标准流程:1. 前端调用 wx.login() 获取 code;2. 后端调用 jscode2session 获取 openid;3. 可选:通过 wx.getPhoneNumber() 获取 phoneCode 绑定手机号")
-    @PostMapping("/wechatLogin")
-    public R<DiningUserVo> wechatLogin(@Valid @RequestBody WeChatLoginDto loginDto, HttpServletRequest request) {
-        log.info("微信小程序登录: code={}, phoneCode={}",
-                loginDto.getCode(),
-                loginDto.getPhoneCode());
-
-        String macIp = getClientIp(request);
-        DiningUserVo userVo = diningUserService.wechatLogin(
-                loginDto.getCode(),
-                loginDto.getPhoneCode(),
-                macIp);
-        if (userVo == null) {
-            return R.fail("登录失败,请检查 code 是否有效(code 有效期5分钟,仅能使用一次)");
-        }
-        return R.data(userVo);
-    }
-
-    @ApiOperation(value = "获取用户信息", notes = "获取当前登录用户的详细信息(从token中获取用户ID)")
-    @GetMapping("/getUserInfo")
-    public R<DiningUserVo> getUserInfo() {
-        // 从 token 获取当前用户ID
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId == null) {
-            return R.fail("用户未登录");
-        }
-
-        log.info("获取用户信息: userId={}", userId);
-
-        DiningUserVo userVo = diningUserService.getUserInfo(userId.longValue());
-        if (userVo == null) {
-            return R.fail("用户不存在或状态异常");
-        }
-        return R.data(userVo);
-    }
-
-    @ApiOperation(value = "更新用户个人信息", notes = "登录后完善资料,支持更新昵称、头像、性别、生日等(从token中获取用户ID)")
-    @PostMapping("/updateProfile")
-    public R<DiningUserVo> updateProfile(@Valid @RequestBody UserProfileUpdateDto dto) {
-        // 从 token 获取当前用户ID
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId == null) {
-            return R.fail("用户未登录");
-        }
-
-        // 使用 token 中的用户ID,忽略 DTO 中的 userId(防止用户修改其他用户的信息)
-        dto.setUserId(userId.longValue());
-        log.info("更新用户个人信息: userId={}", userId);
-
-        DiningUserVo userVo = diningUserService.updateProfile(dto);
-        if (userVo == null) {
-            return R.fail("更新失败,用户不存在");
-        }
-        return R.data(userVo);
-    }
-
-    @ApiOperation(value = "更换手机号", notes = "校验验证码后更新 user_phone,成功后需重新登录(从token中获取用户ID)")
-    @PostMapping("/changePhone")
-    public R<DiningUserVo> changePhone(@Valid @RequestBody ChangePhoneDto dto) {
-        // 从 token 获取当前用户ID
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId == null) {
-            return R.fail("用户未登录");
-        }
-
-        // 使用 token 中的用户ID,忽略 DTO 中的 userId(防止用户修改其他用户的手机号)
-        dto.setUserId(userId.longValue());
-        log.info("更换手机号: userId={}, newPhone={}", userId, dto.getNewPhone());
-
-        DiningUserVo userVo = diningUserService.changePhone(dto);
-        if (userVo == null) {
-            return R.fail("更换失败,请检查验证码或用户状态");
-        }
-        return R.data(userVo);
-    }
-
-    @ApiOperation(value = "校验Token", notes = "验证Token是否有效,支持从请求头Authorization或请求体获取Token")
-    @PostMapping("/verifyToken")
-    public R<TokenVerifyVo> verifyToken(@RequestBody(required = false) VerifyTokenDto dto, HttpServletRequest request) {
-        // 优先从请求体获取 token,如果没有则从请求头获取
-        String token = null;
-        if (dto != null && StringUtils.isNotBlank(dto.getToken())) {
-            token = dto.getToken();
-        } else {
-            // 从请求头获取
-            token = request.getHeader("Authorization");
-        }
-
-        if (StringUtils.isBlank(token)) {
-            return R.fail("Token 不能为空,请通过请求头 Authorization 或请求体传递");
-        }
-
-        log.info("校验Token: token={}", token.length() > 20 ? token.substring(0, 20) + "****" : token);
-
-        TokenVerifyVo verifyVo = diningUserService.verifyToken(token);
-        if (verifyVo == null) {
-            return R.fail("Token 校验失败");
-        }
-
-        if (verifyVo.getValid()) {
-            return R.data(verifyVo);
-        } else {
-            return R.fail(verifyVo.getReason() != null ? verifyVo.getReason() : "Token 无效");
-        }
-    }
-
-    @ApiOperation(value = "解析Token(调试用)", notes = "解析Token内容,用于调试,返回Token中的所有用户信息")
-    @PostMapping("/parseToken")
-    public R<com.alibaba.fastjson.JSONObject> parseToken(@RequestBody(required = false) VerifyTokenDto dto, HttpServletRequest request) {
-        // 优先从请求体获取 token,如果没有则从请求头获取
-        String token = null;
-        if (dto != null && StringUtils.isNotBlank(dto.getToken())) {
-            token = dto.getToken();
-        } else {
-            // 从请求头获取
-            token = request.getHeader("Authorization");
-        }
-
-        if (StringUtils.isBlank(token)) {
-            return R.fail("Token 不能为空");
-        }
-
-        log.info("DiningUserController.parseToken?token={}", token.length() > 20 ? token.substring(0, 20) + "****" : token);
-        com.alibaba.fastjson.JSONObject userInfo = shop.alien.store.util.TokenUtil.parseToken(token);
-        if (userInfo == null) {
-            return R.fail("Token 解析失败,请查看日志获取详细信息");
-        }
-
-        return R.data(userInfo);
-    }
-
-    /**
-     * 获取客户端IP地址
-     */
-    private String getClientIp(HttpServletRequest request) {
-        String ip = request.getHeader("X-Forwarded-For");
-        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
-            ip = request.getHeader("Proxy-Client-IP");
-        }
-        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
-            ip = request.getHeader("WL-Proxy-Client-IP");
-        }
-        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
-            ip = request.getRemoteAddr();
-        }
-        return ip;
-    }
-}

+ 0 - 108
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -21,7 +21,6 @@ import org.springframework.web.multipart.MultipartRequest;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
-import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
 import shop.alien.entity.store.vo.*;
 import shop.alien.entity.storePlatform.StoreLicenseHistory;
 import shop.alien.mapper.*;
@@ -83,9 +82,6 @@ public class StoreInfoController {
     private final PerformanceListService performanceListService;
     private final SportsEquipmentFacilityService sportsEquipmentFacilityService;
 
-    /** 点餐(扫码)侧门店桌台/菜品分类查询,见 {@link ScanOrderStoreInfoService} */
-    private final ScanOrderStoreInfoService diningStoreInfoQueryService;
-
     @ApiOperation("获取所有门店")
     @ApiOperationSupport(order = 1)
     @GetMapping("/getAll")
@@ -1932,110 +1928,6 @@ public class StoreInfoController {
         }
     }
 
-    // —— 以下为原 alien-dining 迁移的扫码/点餐门店查询接口(统一挂到本 Controller,路径仍为 /store/info) ——
-
-    @ApiOperation(value = "根据门店ID查询桌号列表", notes = "查询指定门店下的所有桌号(点餐)")
-    @ApiOperationSupport(order = 900)
-    @GetMapping("/tables")
-    public R<List<StoreTable>> getTablesByStoreId(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
-        log.info("StoreInfoController.getTablesByStoreId?storeId={}", storeId);
-        try {
-            if (storeId == null) {
-                return R.fail("门店ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.getTablesByStoreId(storeId));
-        } catch (Exception e) {
-            log.error("查询桌号列表失败: {}", e.getMessage(), e);
-            return R.fail("查询桌号列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "根据门店ID查询菜品种类列表", notes = "查询指定门店下的所有菜品种类(点餐)")
-    @ApiOperationSupport(order = 901)
-    @GetMapping("/categories")
-    public R<List<StoreCuisineCategory>> getCategoriesByStoreId(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
-        log.info("StoreInfoController.getCategoriesByStoreId?storeId={}", storeId);
-        try {
-            if (storeId == null) {
-                return R.fail("门店ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.getCategoriesByStoreId(storeId));
-        } catch (Exception e) {
-            log.error("查询菜品种类列表失败: {}", e.getMessage(), e);
-            return R.fail("查询菜品种类列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "根据门店ID查询菜品种类及各类别下菜品", notes = "点餐;可选 keyword 按菜品名称模糊查询")
-    @ApiOperationSupport(order = 902)
-    @GetMapping("/categories-with-cuisines")
-    public R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
-            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
-            @ApiParam(value = "菜品名称模糊查询关键词(可选)") @RequestParam(required = false) String keyword) {
-        log.info("StoreInfoController.getCategoriesWithCuisinesByStoreId?storeId={}, keyword={}", storeId, keyword);
-        try {
-            if (storeId == null) {
-                return R.fail("门店ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.getCategoriesWithCuisinesByStoreId(storeId, keyword));
-        } catch (Exception e) {
-            log.error("查询菜品种类及菜品失败: {}", e.getMessage(), e);
-            return R.fail("查询菜品种类及菜品失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "删除菜品种类", notes = "点餐场景;仅删除绑定关系和菜品种类(逻辑删除)")
-    @ApiOperationSupport(order = 903)
-    @DeleteMapping("/category/{categoryId}")
-    public R<Boolean> deleteCategory(
-            @ApiParam(value = "菜品种类ID", required = true) @PathVariable Integer categoryId) {
-        log.info("StoreInfoController.deleteCategory?categoryId={}", categoryId);
-        try {
-            if (categoryId == null) {
-                return R.fail("菜品种类ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.deleteCategory(categoryId));
-        } catch (Exception e) {
-            log.error("删除菜品种类失败: {}", e.getMessage(), e);
-            return R.fail("删除菜品种类失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "根据菜品种类ID查询菜品信息列表", notes = "点餐")
-    @ApiOperationSupport(order = 904)
-    @GetMapping("/cuisines")
-    public R<List<StoreCuisine>> getCuisinesByCategoryId(
-            @ApiParam(value = "菜品种类ID", required = true) @RequestParam Integer categoryId) {
-        log.info("StoreInfoController.getCuisinesByCategoryId?categoryId={}", categoryId);
-        try {
-            if (categoryId == null) {
-                return R.fail("菜品种类ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.getCuisinesByCategoryId(categoryId));
-        } catch (Exception e) {
-            log.error("查询菜品信息列表失败: {}", e.getMessage(), e);
-            return R.fail("查询菜品信息列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "根据商铺ID查询店铺信息和首页展示美食价目表", notes = "点餐")
-    @ApiOperationSupport(order = 905)
-    @GetMapping("/detail/{storeId}")
-    public R<StoreInfoWithHomepageCuisinesDTO> getStoreInfoWithHomepageCuisines(
-            @ApiParam(value = "商铺ID", required = true) @PathVariable Integer storeId) {
-        log.info("StoreInfoController.getStoreInfoWithHomepageCuisines?storeId={}", storeId);
-        try {
-            if (storeId == null) {
-                return R.fail("商铺ID不能为空");
-            }
-            return R.data(diningStoreInfoQueryService.getStoreInfoWithHomepageCuisines(storeId));
-        } catch (Exception e) {
-            log.error("查询店铺信息和首页展示美食价目表失败: {}", e.getMessage(), e);
-            return R.fail("查询店铺信息和首页展示美食价目表失败: " + e.getMessage());
-        }
-    }
 
     /**
      * 店铺信息(包含商户头像)

+ 0 - 578
alien-store/src/main/java/shop/alien/store/controller/StoreOrderController.java

@@ -1,578 +0,0 @@
-package shop.alien.store.controller;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-import shop.alien.store.service.CartService;
-import shop.alien.store.service.SseService;
-import shop.alien.store.service.StoreOrderService;
-import shop.alien.store.util.TokenUtil;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.*;
-import shop.alien.entity.store.dto.AddCartItemDTO;
-import shop.alien.entity.store.dto.CartDTO;
-import shop.alien.entity.store.dto.ChangeTableDTO;
-import shop.alien.entity.store.dto.CreateOrderDTO;
-import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
-import shop.alien.entity.store.vo.OrderInfoVO;
-import shop.alien.entity.store.vo.OrderDetailWithChangeLogVO;
-import shop.alien.entity.store.vo.StoreOrderPageVO;
-import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.StoreOrderDetailMapper;
-import shop.alien.mapper.StoreTableMapper;
-
-import javax.validation.Valid;
-import java.util.List;
-
-/**
- * 订单管理控制器
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Api(tags = {"小程序-订单管理"})
-@CrossOrigin
-@RestController
-@RequestMapping("/store/order")
-@RequiredArgsConstructor
-public class StoreOrderController {
-
-    private final StoreOrderService orderService;
-    private final CartService cartService;
-    private final SseService sseService;
-    private final StoreOrderDetailMapper orderDetailMapper;
-    private final StoreTableMapper storeTableMapper;
-    private final StoreInfoMapper storeInfoMapper;
-
-    @ApiOperation(value = "获取购物车", notes = "根据桌号ID获取购物车信息")
-    @GetMapping("/cart/{tableId}")
-    public R<CartDTO> getCart(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
-        log.info("StoreOrderController.getCart?tableId={}", tableId);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            CartDTO cart = cartService.getCart(tableId);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("获取购物车失败: {}", e.getMessage(), e);
-            return R.fail("获取购物车失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "添加商品到购物车", notes = "添加商品到购物车,并推送SSE和WebSocket消息")
-    @PostMapping("/cart/add")
-    public R<CartDTO> addCartItem(@Valid @RequestBody AddCartItemDTO dto) {
-        log.info("StoreOrderController.addCartItem?dto={}", dto);
-        try {
-            // 验证 token(用户信息在 CartService 中从 token 获取)
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            CartDTO cart = cartService.addItem(dto);
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(dto.getTableId(), cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(dto.getTableId(), cart);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("添加商品到购物车失败: {}", e.getMessage(), e);
-            return R.fail("添加商品到购物车失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "更新购物车商品数量", notes = "更新购物车中商品的数量,并推送SSE和WebSocket消息")
-    @PutMapping("/cart/update")
-    public R<CartDTO> updateCartItem(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId,
-            @ApiParam(value = "数量", required = true) @RequestParam Integer quantity) {
-        log.info("StoreOrderController.updateCartItem?tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            CartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(tableId, cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("更新购物车商品数量失败: {}", e.getMessage(), e);
-            return R.fail("更新购物车商品数量失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "删除购物车商品", notes = "从购物车中删除商品,并推送SSE和WebSocket消息")
-    @DeleteMapping("/cart/remove")
-    public R<CartDTO> removeCartItem(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId) {
-        log.info("StoreOrderController.removeCartItem?tableId={}, cuisineId={}", tableId, cuisineId);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            CartDTO cart = cartService.removeItem(tableId, cuisineId);
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(tableId, cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("删除购物车商品失败: {}", e.getMessage(), e);
-            return R.fail("删除购物车商品失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "清空购物车", notes = "清空购物车中所有商品(保留餐具和已下单商品),并推送SSE和WebSocket消息")
-    @DeleteMapping("/cart/clear")
-    public R<CartDTO> clearCart(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
-        log.info("StoreOrderController.clearCart?tableId={}", tableId);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            
-            // 清空购物车(会自动保留已下单的商品和餐具)
-            cartService.clearCart(tableId);
-            
-            // 获取清空后的购物车(包含保留的餐具和已下单商品)
-            CartDTO cart = cartService.getCart(tableId);
-            
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(tableId, cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
-            
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("清空购物车失败: {}", e.getMessage(), e);
-            return R.fail("清空购物车失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "设置用餐人数", notes = "设置用餐人数,自动添加或更新餐具到购物车")
-    @PostMapping("/cart/set-diner-count")
-    public R<CartDTO> setDinerCount(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "用餐人数", required = true) @RequestParam Integer dinerCount) {
-        log.info("StoreOrderController.setDinerCount?tableId={}, dinerCount={}", tableId, dinerCount);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            if (dinerCount == null || dinerCount <= 0) {
-                return R.fail("用餐人数必须大于0");
-            }
-            CartDTO cart = cartService.setDinerCount(tableId, dinerCount);
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(tableId, cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("设置用餐人数失败: {}", e.getMessage(), e);
-            return R.fail("设置用餐人数失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "更新餐具数量", notes = "更新购物车中餐具的数量,并推送SSE和WebSocket消息。餐具数量为0或未传时不往购物车加餐具(0会移除已有餐具项)")
-    @PutMapping("/cart/update-tableware")
-    public R<CartDTO> updateTablewareQuantity(
-            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
-            @ApiParam(value = "餐具数量,0或未传则不往购物车加餐具") @RequestParam(required = false) Integer quantity) {
-        log.info("StoreOrderController.updateTablewareQuantity?tableId={}, quantity={}", tableId, quantity);
-        try {
-            // 验证 token
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            if (quantity != null && quantity < 0) {
-                return R.fail("餐具数量不能小于0");
-            }
-            // 餐具数量为 0 或 null 时不往购物车加餐具:0 则移除已有餐具项,null 则直接返回当前购物车
-            if (quantity == null) {
-                CartDTO cart = cartService.getCart(tableId);
-                sseService.pushCartUpdate(tableId, cart);
-                return R.data(cart);
-            }
-            if (quantity == 0) {
-                CartDTO cart = cartService.updateTablewareQuantity(tableId, 0);
-                sseService.pushCartUpdate(tableId, cart);
-                return R.data(cart);
-            }
-            CartDTO cart = cartService.updateTablewareQuantity(tableId, quantity);
-            // 推送购物车更新消息(SSE)
-            sseService.pushCartUpdate(tableId, cart);
-            // 推送购物车更新消息(WebSocket)
-//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("更新餐具数量失败: {}", e.getMessage(), e);
-            return R.fail("更新餐具数量失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "创建订单(下单)", notes = "从购物车创建订单,不立即支付。备注:创建/更新时传入,更新订单(加餐)时为覆盖")
-    @PostMapping("/create")
-    public R<shop.alien.entity.store.vo.OrderSuccessVO> createOrder(@Valid @RequestBody CreateOrderDTO dto) {
-        log.info("StoreOrderController.createOrder?dto={}", dto);
-        try {
-            // 验证 token(用户信息在 StoreOrderService 中从 token 获取)
-            if (!TokenUtil.hasValidToken()) {
-                return R.fail("用户未登录");
-            }
-            // 限制备注长度
-            if (dto.getRemark() != null && dto.getRemark().length() > 30) {
-                dto.setRemark(dto.getRemark().substring(0, 30));
-            }
-
-            // 设置不立即支付
-            dto.setImmediatePay(0);
-            StoreOrder order = orderService.createOrder(dto);
-
-            // 转换为OrderSuccessVO
-            shop.alien.entity.store.vo.OrderSuccessVO vo = new shop.alien.entity.store.vo.OrderSuccessVO();
-            vo.setOrderId(order.getId());
-            vo.setOrderNo(order.getOrderNo());
-            vo.setTableNumber(order.getTableNumber());
-            vo.setDinerCount(order.getDinerCount());
-            vo.setOrderStatus(order.getOrderStatus());
-
-            // 查询门店信息
-            StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
-            vo.setStoreName(storeInfo != null ? storeInfo.getStoreName() : null);
-
-            // 推送订单创建消息
-            sseService.pushCartUpdate(dto.getTableId(), order);
-            return R.data(vo);
-        } catch (Exception e) {
-            log.error("创建订单失败: {}", e.getMessage(), e);
-            return R.fail("创建订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "支付订单", notes = "支付订单,支付成功后订单状态变为已支付(1),需要单独调用完成订单接口将订单状态改为已完成(3)")
-    @PostMapping("/pay/{orderId}")
-    public R<Object> payOrder(
-            @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId,
-            @ApiParam(value = "支付方式(1:微信, 2:支付宝, 3:现金)", required = true) @RequestParam Integer payType) {
-        log.info("StoreOrderController.payOrder?orderId={}, payType={}", orderId, payType);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            
-            StoreOrder order = orderService.getOrderById(orderId);
-            if (order == null) {
-                return R.fail("订单不存在");
-            }
-
-            if (order.getOrderStatus() != 0) {
-                return R.fail("订单状态不正确,无法支付");
-            }
-
-            // 如果是微信支付,调用微信支付接口
-            if (payType == 1) {
-                // TODO: 调用微信支付接口,返回支付参数
-                // 这里需要集成微信支付SDK,返回支付参数给前端拉起支付
-                // 支付成功后通过回调接口更新订单状态
-                // 暂时先更新订单状态为已支付(实际应该等支付回调)
-                order = orderService.payOrder(orderId, payType);
-                return R.data(order);
-            } else {
-                // 其他支付方式(支付宝、现金)直接更新为已支付
-                order = orderService.payOrder(orderId, payType);
-                return R.data(order);
-            }
-        } catch (Exception e) {
-            log.error("支付订单失败: {}", e.getMessage(), e);
-            return R.fail("支付订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "取消订单", notes = "取消订单")
-    @PostMapping("/cancel/{orderId}")
-    public R<Boolean> cancelOrder(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.cancelOrder?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = orderService.cancelOrder(orderId);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("取消订单失败: {}", e.getMessage(), e);
-            return R.fail("取消订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "查询订单详情", notes = "根据订单ID查询订单详情,包含订单基本信息和按批次分组的变更记录,用于展示每次下单/加餐都加了什么商品")
-    @GetMapping("/detail/{orderId}")
-    public R<OrderDetailWithChangeLogVO> getOrderDetail(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.getOrderDetail?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            OrderDetailWithChangeLogVO orderDetail = orderService.getOrderDetailWithChangeLog(orderId);
-            return R.data(orderDetail);
-        } catch (Exception e) {
-            log.error("查询订单详情失败: {}", e.getMessage(), e);
-            return R.fail("查询订单详情失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "查询订单明细", notes = "根据订单ID查询订单明细列表")
-    @GetMapping("/detail/list/{orderId}")
-    public R<List<StoreOrderDetail>> getOrderDetailList(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.getOrderDetailList?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StoreOrderDetail> wrapper =
-                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
-            wrapper.eq(StoreOrderDetail::getOrderId, orderId);
-            wrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-            wrapper.orderByDesc(StoreOrderDetail::getCreatedTime);
-            List<StoreOrderDetail> details = orderDetailMapper.selectList(wrapper);
-            return R.data(details);
-        } catch (Exception e) {
-            log.error("查询订单明细失败: {}", e.getMessage(), e);
-            return R.fail("查询订单明细失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "查询订单信息", notes = "根据订单ID查询订单完整信息(包含订单基本信息、菜品清单、价格明细)")
-    @GetMapping("/info/{orderId}")
-    public R<OrderInfoVO> getOrderInfo(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.getOrderInfo?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            OrderInfoVO orderInfo = orderService.getOrderInfo(orderId);
-            return R.data(orderInfo);
-        } catch (Exception e) {
-            log.error("查询订单信息失败: {}", e.getMessage(), e);
-            return R.fail("查询订单信息失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "查询订单变更记录", notes = "根据订单ID查询订单的所有变更记录(按批次分组),用于展示每次下单/加餐都加了什么商品")
-    @GetMapping("/change-log/{orderId}")
-    public R<List<OrderChangeLogBatchVO>> getOrderChangeLogs(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.getOrderChangeLogs?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            List<OrderChangeLogBatchVO> changeLogs = orderService.getOrderChangeLogs(orderId);
-            return R.data(changeLogs);
-        } catch (Exception e) {
-            log.error("查询订单变更记录失败: {}", e.getMessage(), e);
-            return R.fail("查询订单变更记录失败: " + e.getMessage());
-        }
-    }
-
-
-    @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单列表,包含订单中的菜品数量、菜品名称、菜品图片。支持按订单编号或菜品名称搜索(限15字)")
-    @GetMapping("/page")
-    public R<IPage<StoreOrderPageVO>> getOrderPage(
-            @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
-            @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
-            @ApiParam(value = "门店ID") @RequestParam(required = false) Integer storeId,
-            @ApiParam(value = "桌号ID") @RequestParam(required = false) Integer tableId,
-            @ApiParam(value = "订单状态:0=进行中(待支付+已支付),3=已完成") @RequestParam(required = false) Integer orderStatus,
-            @ApiParam(value = "搜索关键词(订单编号或菜品名称,限15字)") @RequestParam(required = false) String keyword) {
-        log.info("StoreOrderController.getOrderPage?current={}, size={}, storeId={}, tableId={}, orderStatus={}, keyword={}", current, size, storeId, tableId, orderStatus, keyword);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            Page<StoreOrder> page = new Page<>(current, size);
-            IPage<StoreOrderPageVO> result = orderService.getOrderPageWithCuisines(page, storeId, tableId, orderStatus, keyword);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("分页查询订单列表失败: {}", e.getMessage(), e);
-            return R.fail("分页查询订单列表失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "查询我的订单", notes = "通过标识查询我的未支付订单或历史订单,包含订单中的菜品数量、菜品名称、菜品图片。type: 0或unpaid-未支付订单, 1或history-历史订单")
-    @GetMapping("/my-orders")
-    public R<IPage<StoreOrderPageVO>> getMyOrders(
-            @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
-            @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
-            @ApiParam(value = "订单类型(0或unpaid:未支付订单, 1或history:历史订单)", required = true) @RequestParam String type) {
-        log.info("StoreOrderController.getMyOrders?current={}, size={}, type={}", current, size, type);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            Page<StoreOrder> page = new Page<>(current, size);
-            IPage<StoreOrderPageVO> result = orderService.getMyOrdersWithCuisines(page, type);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("查询我的订单失败: {}", e.getMessage(), e);
-            return R.fail("查询我的订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "换桌", notes = "换桌并迁移购物车、未完成的订单以及其他关联表数据")
-    @PostMapping("/change-table")
-    public R<CartDTO> changeTable(@Valid @RequestBody ChangeTableDTO dto) {
-        log.info("StoreOrderController.changeTable?dto={}", dto);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-
-            // 调用Service层处理换桌业务逻辑
-            CartDTO cart = orderService.changeTable(dto.getFromTableId(), dto.getToTableId(), dto.getChangeReason(), userId);
-
-            return R.data(cart);
-        } catch (Exception e) {
-            log.error("换桌失败: {}", e.getMessage(), e);
-            return R.fail("换桌失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "建立SSE连接", notes = "建立SSE连接,用于接收购物车更新消息")
-    @GetMapping(value = "/sse/{tableId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
-    public SseEmitter createSseConnection(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
-        // 验证 token
-        if (!TokenUtil.hasValidToken()) {
-            log.warn("建立SSE连接失败: 用户未登录, tableId={}", tableId);
-            return null;
-        }
-        log.info("建立SSE连接, tableId={}", tableId);
-        return sseService.createConnection(tableId);
-    }
-
-    @ApiOperation(value = "完成订单", notes = "完成订单,将已支付状态的订单改为已完成状态。订单状态:0-待支付,1-已支付,3-已完成。只有已支付状态的订单才能完成")
-    @PostMapping("/complete/{orderId}")
-    public R<Boolean> completeOrder(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.completeOrder?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = orderService.completeOrder(orderId);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("完成订单失败: {}", e.getMessage(), e);
-            return R.fail("完成订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "商家手动完成订单", notes = "供商家使用,手动点击完成订单。不校验订单是否处于已支付状态,直接将订单状态改为已完成。订单状态:0-待支付,1-已支付,2-已取消,3-已完成")
-    @PostMapping("/complete-by-merchant/{orderId}")
-    public R<Boolean> completeOrderByMerchant(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
-        log.info("StoreOrderController.completeOrderByMerchant?orderId={}", orderId);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            boolean result = orderService.completeOrderByMerchant(orderId);
-            return R.data(result);
-        } catch (Exception e) {
-            log.error("商家手动完成订单失败: {}", e.getMessage(), e);
-            return R.fail("商家手动完成订单失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "更新订单优惠券", notes = "重新选择优惠券")
-    @PostMapping("/update-coupon")
-    public R<StoreOrder> updateOrderCoupon(@Valid @RequestBody shop.alien.entity.store.dto.UpdateOrderCouponDTO dto) {
-        log.info("StoreOrderController.updateOrderCoupon?dto={}", dto);
-        try {
-            // 从 token 获取用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-            StoreOrder order = orderService.updateOrderCoupon(dto.getOrderId(), dto.getCouponId());
-            return R.data(order);
-        } catch (Exception e) {
-            log.error("更新订单优惠券失败: {}", e.getMessage(), e);
-            return R.fail("更新订单优惠券失败: " + e.getMessage());
-        }
-    }
-
-    @ApiOperation(value = "管理员重置餐桌", notes = "管理员重置餐桌:删除购物车数据、未支付/已取消的订单数据,并重置餐桌表初始化。已支付/已完成的订单会被保留,避免数据丢失")
-    @PostMapping("/admin/reset-table/{tableId}")
-    public R<Boolean> resetTable(@ApiParam(value = "餐桌ID", required = true) @PathVariable Integer tableId) {
-        log.info("StoreOrderController.resetTable?tableId={}", tableId);
-        try {
-            // TODO: 这里可以添加管理员权限验证
-            // if (!isAdmin(userId)) {
-            //     return R.fail("无权限执行此操作");
-            // }
-            
-            boolean result = orderService.resetTable(tableId);
-            if (result) {
-                // 推送购物车更新消息(清空购物车)
-                CartDTO emptyCart = new CartDTO();
-                emptyCart.setTableId(tableId);
-                emptyCart.setItems(java.util.Collections.emptyList());
-                emptyCart.setTotalAmount(java.math.BigDecimal.ZERO);
-                emptyCart.setTotalQuantity(0);
-                
-                // 查询桌号信息
-                StoreTable table = storeTableMapper.selectById(tableId);
-                if (table != null) {
-                    emptyCart.setTableNumber(table.getTableNumber());
-                    emptyCart.setStoreId(table.getStoreId());
-                }
-                
-                sseService.pushCartUpdate(tableId, emptyCart);
-                return R.data(true);
-            } else {
-                return R.fail("重置餐桌失败");
-            }
-        } catch (Exception e) {
-            log.error("重置餐桌失败: {}", e.getMessage(), e);
-            return R.fail("重置餐桌失败: " + e.getMessage());
-        }
-    }
-}

+ 0 - 34
alien-store/src/main/java/shop/alien/store/dto/ChangePhoneDto.java

@@ -1,34 +0,0 @@
-package shop.alien.store.dto;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-
-/**
- * 更换手机号请求
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("更换手机号请求")
-public class ChangePhoneDto {
-
-    @ApiModelProperty(value = "用户ID", required = true)
-    @NotNull(message = "用户ID不能为空")
-    private Long userId;
-
-    @ApiModelProperty(value = "新手机号", required = true)
-    @NotBlank(message = "新手机号不能为空")
-    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
-    private String newPhone;
-
-    @ApiModelProperty(value = "验证码", required = true)
-    @NotBlank(message = "验证码不能为空")
-    private String code;
-}

+ 0 - 56
alien-store/src/main/java/shop/alien/store/dto/UserProfileUpdateDto.java

@@ -1,56 +0,0 @@
-package shop.alien.store.dto;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import java.util.Date;
-
-/**
- * 用户个人信息更新DTO
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("用户个人信息更新请求")
-public class UserProfileUpdateDto {
-
-    @ApiModelProperty(value = "用户ID", required = true)
-    @NotNull(message = "用户ID不能为空")
-    private Long userId;
-
-    @ApiModelProperty(value = "昵称")
-    private String nickName;
-
-    @ApiModelProperty(value = "头像URL")
-    private String avatarUrl;
-
-    @ApiModelProperty(value = "性别(男/女)")
-    private String gender;
-
-    @ApiModelProperty(value = "生日", example = "1990-01-01")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
-    private Date birthday;
-
-    @ApiModelProperty(value = "真实姓名")
-    private String realName;
-
-    @ApiModelProperty(value = "省份")
-    private String province;
-
-    @ApiModelProperty(value = "城市")
-    private String city;
-
-    @ApiModelProperty(value = "区县")
-    private String district;
-
-    @ApiModelProperty(value = "详细地址")
-    private String address;
-
-    @ApiModelProperty(value = "个人简介")
-    private String jianjie;
-}

+ 0 - 20
alien-store/src/main/java/shop/alien/store/dto/VerifyTokenDto.java

@@ -1,20 +0,0 @@
-package shop.alien.store.dto;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-/**
- * Token 校验请求DTO
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("Token校验请求")
-public class VerifyTokenDto {
-
-    @ApiModelProperty(value = "Token(可选,如果不传则从请求头 Authorization 获取)", required = false)
-    private String token;
-}

+ 0 - 29
alien-store/src/main/java/shop/alien/store/dto/WeChatLoginDto.java

@@ -1,29 +0,0 @@
-package shop.alien.store.dto;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotBlank;
-
-/**
- * 微信小程序登录DTO
- * 标准流程:通过 wx.login() 获取 code,调用 jscode2session 获取 openid
- * 可选:通过 wx.getPhoneNumber() 获取 phoneCode,用于绑定手机号
- *
- * @author ssk
- * @version 2.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("微信小程序登录请求")
-public class WeChatLoginDto {
-
-    @ApiModelProperty(value = "微信登录凭证 code(通过 wx.login() 获取,必填)", required = true)
-    @NotBlank(message = "code不能为空,请通过 wx.login() 获取")
-    private String code;
-
-    @ApiModelProperty(value = "手机号凭证 code(通过 wx.getPhoneNumber() 获取,可选,用于绑定手机号)", required = false)
-    private String phoneCode;
-
-}

+ 0 - 48
alien-store/src/main/java/shop/alien/store/enums/OrderStatus.java

@@ -1,48 +0,0 @@
-package shop.alien.store.enums;
-
-/**
- * 订单状态枚举
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-public enum OrderStatus {
-    /**
-     * 待支付
-     */
-    PENDING_PAYMENT(0, "待支付"),
-    /**
-     * 已支付
-     */
-    PAID(1, "已支付"),
-    /**
-     * 制作中
-     */
-    PREPARING(2, "制作中"),
-    /**
-     * 已完成
-     */
-    COMPLETED(3, "已完成"),
-    /**
-     * 已取消
-     */
-    CANCELLED(4, "已取消");
-
-    private final Integer code;
-    private final String desc;
-
-    OrderStatus(Integer code, String desc) {
-        this.code = code;
-        this.desc = desc;
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-}
-

+ 0 - 80
alien-store/src/main/java/shop/alien/store/feign/AlienStoreFeign.java

@@ -1,80 +0,0 @@
-package shop.alien.store.feign;
-
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RequestPart;
-import org.springframework.web.multipart.MultipartFile;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeCollect;
-import shop.alien.entity.store.vo.LifeDiscountCouponVo;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 嵌入在 alien-store 内的点餐子包通过 Feign 复用本机优惠券/短信/收藏等能力(与其它微服务部署方式一致时可走注册中心)。
- */
-@FeignClient(name = "alienStoreFeign", url = "${feign.alienStore.url:}", contextId = "alienStoreFeignForDining")
-public interface AlienStoreFeign {
-
-    @GetMapping("ali/checkSmsCode")
-    R<?> checkSmsCode(
-            @RequestParam("phone") String phone,
-            @RequestParam("appType") Integer appType,
-            @RequestParam("businessType") Integer businessType,
-            @RequestParam("code") Integer code);
-
-    @GetMapping("life-discount-coupon/getUserCouponList")
-    R<List<LifeDiscountCouponVo>> getUserCouponList(
-            @RequestHeader(value = "Authorization", required = false) String authorization,
-            @RequestParam("tabType") String tabType,
-            @RequestParam(value = "page", defaultValue = "1") int page,
-            @RequestParam(value = "size", defaultValue = "10") int size,
-            @RequestParam(value = "type", required = false) Integer type,
-            @RequestParam(value = "couponType", required = false) Integer couponType,
-            @RequestParam(value = "storeId", required = false) String storeId,
-            @RequestParam(value = "storeName", required = false) String storeName);
-
-    @GetMapping("life-discount-coupon/getCounponDetailById")
-    R<LifeDiscountCouponVo> getCounponDetailById(
-            @RequestHeader(value = "Authorization", required = false) String authorization,
-            @RequestParam("counponId") String counponId);
-
-    @GetMapping("life-discount-coupon/getStoreUserUsableCouponList")
-    R<Map<String, Object>> getStoreUserUsableCouponList(
-            @RequestHeader(value = "Authorization", required = false) String authorization,
-            @RequestParam("storeId") String storeId,
-            @RequestParam("amount") BigDecimal amount,
-            @RequestParam(value = "couponType", required = false) Integer couponType);
-
-    @GetMapping("life-discount-coupon/getStoreUserCouponList")
-    R<List<LifeDiscountCouponVo>> getStoreUserCouponList(
-            @RequestHeader(value = "Authorization", required = false) String authorization,
-            @RequestParam("storeId") String storeId,
-            @RequestParam(value = "couponType", required = false) Integer couponType);
-
-    @GetMapping("life-discount-coupon/getStoreAllCouponList")
-    R<Page<LifeDiscountCouponVo>> getStoreAllCouponList(
-            @RequestHeader(value = "Authorization", required = false) String authorization,
-            @RequestParam(value = "page", defaultValue = "1") int page,
-            @RequestParam(value = "size", defaultValue = "10") int size,
-            @RequestParam("storeId") String storeId,
-            @RequestParam(value = "couponName", required = false) String couponName,
-            @RequestParam("tab") String tab,
-            @RequestParam(value = "couponsFromType", defaultValue = "1") int couponsFromType,
-            @RequestParam(value = "couponStatus", defaultValue = "1", required = false) int couponStatus,
-            @RequestParam(value = "couponType", required = false) Integer couponType);
-
-    @PostMapping("/collect/addCollect")
-    R<Boolean> addCollect(@RequestBody LifeCollect lifeCollect);
-
-    @PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    R<String> uploadFile(@RequestPart("file") MultipartFile file);
-}

+ 273 - 0
alien-store/src/main/java/shop/alien/store/feign/DiningServiceFeign.java

@@ -0,0 +1,273 @@
+package shop.alien.store.feign;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreTable;
+import shop.alien.entity.store.dto.CartDTO;
+import shop.alien.entity.store.dto.ChangeTableDTO;
+import shop.alien.entity.store.vo.*;
+
+import java.util.List;
+
+/**
+ * 点餐服务 Feign 客户端
+ * 用于 alien-store 模块调用 alien-dining 模块的接口
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/01/XX
+ */
+@FeignClient(name = "alien-dining", url = "${feign.alienDining.url:}")
+public interface DiningServiceFeign {
+
+    // ==================== 点餐相关接口 ====================
+
+    /**
+     * 查询餐桌是否处于就餐中(免登录可调用)
+     *
+     * @param tableId 桌号ID
+     * @return R.data 为 TableDiningStatusVO(inDining、dinerCount)
+     */
+    @GetMapping("/store/dining/table-dining-status")
+    R<TableDiningStatusVO> getTableDiningStatus(@RequestParam("tableId") Integer tableId);
+
+    /**
+     * 获取点餐页面信息
+     *
+     * @param authorization 请求头 Authorization,供 dining 解析当前用户
+     * @param tableId       桌号ID
+     * @param dinerCount    就餐人数(首客必传;餐桌已就餐中时可省略)
+     * @return R.data 为 DiningPageInfoVO
+     */
+    @GetMapping("/store/dining/page-info")
+    R<DiningPageInfoVO> getDiningPageInfo(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam("tableId") Integer tableId,
+            @RequestParam(value = "dinerCount", required = false) Integer dinerCount);
+
+    /**
+     * 搜索菜品
+     *
+     * @param authorization 请求头 Authorization
+     * @param storeId       门店ID
+     * @param keyword       搜索关键词
+     * @param tableId       桌号ID
+     * @return R.data 为 List&lt;CuisineListVO&gt;
+     */
+    @GetMapping("/store/dining/search")
+    R<List<CuisineListVO>> searchCuisines(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam("keyword") String keyword,
+            @RequestParam("tableId") Integer tableId);
+
+    /**
+     * 根据分类获取菜品列表
+     *
+     * @param authorization 请求头 Authorization
+     * @param storeId       门店ID
+     * @param categoryId    分类ID(可为空,查询所有)
+     * @param tableId       桌号ID
+     * @param page          页码(默认1)
+     * @param size          每页数量(默认12)
+     * @return R.data 为 List&lt;CuisineListVO&gt;
+     */
+    @GetMapping("/store/dining/cuisines")
+    R<List<CuisineListVO>> getCuisinesByCategory(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam(value = "categoryId", required = false) Integer categoryId,
+            @RequestParam("tableId") Integer tableId,
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "size", defaultValue = "12") Integer size);
+
+    /**
+     * 获取菜品详情
+     *
+     * @param authorization 请求头 Authorization
+     * @param cuisineId     菜品ID
+     * @param tableId       桌号ID
+     * @return R.data 为 CuisineDetailVO
+     */
+    @GetMapping("/store/dining/cuisine/{cuisineId}")
+    R<CuisineDetailVO> getCuisineDetail(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @PathVariable("cuisineId") Integer cuisineId,
+            @RequestParam("tableId") Integer tableId);
+
+    /**
+     * 获取可领取的优惠券列表
+     *
+     * @param authorization 请求头 Authorization
+     * @param storeId       门店ID
+     * @return R.data 为 List&lt;AvailableCouponVO&gt;
+     */
+    @GetMapping("/store/dining/coupons/available")
+    R<List<AvailableCouponVO>> getAvailableCoupons(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam("storeId") Integer storeId);
+
+    // ==================== 订单相关接口 ====================
+
+    /**
+     * 获取购物车
+     *
+     * @param authorization 请求头 Authorization
+     * @param tableId       桌号ID
+     * @return R.data 为 CartDTO
+     */
+    @GetMapping("/store/order/cart/{tableId}")
+    R<CartDTO> getCart(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @PathVariable("tableId") Integer tableId);
+
+    /**
+     * 换桌(迁移购物车、未完成订单及关联数据,支持点餐未下单场景,无需订单号)
+     *
+     * @param authorization 请求头 Authorization
+     * @param dto            原桌号ID、目标桌号ID、换桌原因
+     * @return R.data 为迁移后的购物车 CartDTO
+     */
+    @PostMapping("/store/order/change-table")
+    R<CartDTO> changeTable(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestBody ChangeTableDTO dto);
+
+    /**
+     * 获取订单详情
+     *
+     * @param authorization 请求头 Authorization
+     * @param orderId       订单ID
+     * @return R.data 为 OrderDetailWithChangeLogVO
+     */
+    @GetMapping("/store/order/detail/{orderId}")
+    R<OrderDetailWithChangeLogVO> getOrderDetail(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @PathVariable("orderId") Integer orderId);
+
+    /**
+     * 获取订单列表(分页)
+     *
+     * @param authorization 请求头 Authorization
+     * @param page          页码
+     * @param size          每页数量
+     * @param status        订单状态(可选)
+     * @return R.data 为 IPage&lt;StoreOrderPageVO&gt;
+     */
+    @GetMapping("/store/order/list")
+    R<IPage<StoreOrderPageVO>> getOrderList(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "size", defaultValue = "10") Integer size,
+            @RequestParam(value = "status", required = false) Integer status);
+
+    /**
+     * 分页查询订单列表
+     * 包含订单中的菜品数量、菜品名称、菜品图片。支持按订单编号或菜品名称搜索(限15字)
+     *
+     * @param authorization 请求头 Authorization,供 dining 解析当前用户
+     * @param current       页码(默认1)
+     * @param size         每页数量(默认10)
+     * @param storeId       门店ID(可选)
+     * @param tableId       桌号ID(可选)
+     * @param orderStatus   订单状态(可选,0:待支付, 1:已支付, 2:已取消, 3:已完成)
+     * @param keyword       搜索关键词(订单编号或菜品名称,限15字)(可选)
+     * @return R.data 为 Page&lt;StoreOrderPageVO&gt;(使用具体的 Page 实现类,避免 IPage 反序列化问题)
+     */
+    @GetMapping("/store/order/page")
+    R<Page<StoreOrderPageVO>> getOrderPage(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @RequestParam(value = "current", defaultValue = "1") Long current,
+            @RequestParam(value = "size", defaultValue = "10") Long size,
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "tableId", required = false) Integer tableId,
+            @RequestParam(value = "orderStatus", required = false) Integer orderStatus,
+            @RequestParam(value = "keyword", required = false) String keyword);
+
+    /**
+     * 查询订单变更记录
+     *
+     * @param authorization 请求头 Authorization
+     * @param orderId       订单ID
+     * @return R.data 为 List&lt;OrderChangeLogBatchVO&gt;
+     */
+    @GetMapping("/store/order/change-log/{orderId}")
+    R<List<OrderChangeLogBatchVO>> getOrderChangeLogs(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @PathVariable("orderId") Integer orderId);
+
+    /**
+     * 商家手动完成订单(不校验支付状态)
+     *
+     * @param authorization 请求头 Authorization
+     * @param orderId       订单ID
+     * @return R.data 为 Boolean(是否成功)
+     */
+    @PostMapping("/store/order/complete-by-merchant/{orderId}")
+    R<Boolean> completeOrderByMerchant(
+            @RequestHeader(value = "Authorization", required = false) String authorization,
+            @PathVariable("orderId") Integer orderId);
+
+    // ==================== 用户相关接口 ====================
+
+    /**
+     * 获取用户信息
+     * 注意:返回类型使用 Object,因为 DiningUserVo 在 alien-dining 模块中
+     * 调用方需要自行转换为对应的 VO 对象
+     *
+     * @param authorization 请求头 Authorization
+     * @return R.data 为用户信息对象
+     */
+    @GetMapping("/dining/user/getUserInfo")
+    R<Object> getUserInfo(
+            @RequestHeader(value = "Authorization", required = false) String authorization);
+
+    // ==================== 门店信息接口 ====================
+
+    /**
+     * 根据门店ID查询桌号列表
+     *
+     * @param storeId 门店ID
+     * @return R.data 为 List&lt;StoreTable&gt;
+     */
+    @GetMapping("/store/info/tables")
+    R<List<StoreTable>> getTablesByStoreId(
+            @RequestParam("storeId") Integer storeId);
+
+    /**
+     * 根据门店ID查询菜品种类及各类别下菜品(可选按菜品名称模糊查询)
+     *
+     * @param storeId 门店ID
+     * @param keyword 菜品名称模糊查询关键词(可选)
+     * @return R.data 为 List&lt;CategoryWithCuisinesVO&gt;
+     */
+    @GetMapping("/store/info/categories-with-cuisines")
+    R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam(value = "keyword", required = false) String keyword);
+
+    /**
+     * 删除菜品种类(仅解除绑定+逻辑删分类,价目表菜品不变)
+     *
+     * @param categoryId 菜品种类ID
+     * @return R.data 为 Boolean
+     */
+    @DeleteMapping("/store/info/category/{categoryId}")
+    R<Boolean> deleteCategory(@PathVariable("categoryId") Integer categoryId);
+
+    // ==================== 文件上传接口 ====================
+
+    /**
+     * 上传图片到OSS(单个文件上传,支持图片、视频或PDF)
+     *
+     * @param file 文件对象
+     * @return R.data 为文件路径(String)
+     */
+    @PostMapping(value = "/dining/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    R<String> uploadFile(@RequestPart("file") MultipartFile file);
+}

+ 0 - 121
alien-store/src/main/java/shop/alien/store/service/CartService.java

@@ -1,121 +0,0 @@
-package shop.alien.store.service;
-
-import shop.alien.entity.store.dto.AddCartItemDTO;
-import shop.alien.entity.store.dto.CartDTO;
-
-/**
- * 购物车服务接口
- *
- * @author system
- * @since 2025-01-XX
- */
-public interface CartService {
-
-    /**
-     * 获取购物车
-     *
-     * @param tableId 桌号ID
-     * @return 购物车信息
-     */
-    CartDTO getCart(Integer tableId);
-
-    /**
-     * 添加商品到购物车
-     *
-     * @param dto 添加购物车商品DTO
-     * @return 购物车信息
-     */
-    CartDTO addItem(AddCartItemDTO dto);
-
-    /**
-     * 更新购物车商品数量
-     *
-     * @param tableId   桌号ID
-     * @param cuisineId 菜品ID
-     * @param quantity  数量
-     * @return 购物车信息
-     */
-    CartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity);
-
-    /**
-     * 删除购物车商品
-     *
-     * @param tableId   桌号ID
-     * @param cuisineId 菜品ID
-     * @return 购物车信息
-     */
-    CartDTO removeItem(Integer tableId, Integer cuisineId);
-
-    /**
-     * 清空购物车
-     *
-     * @param tableId 桌号ID
-     */
-    void clearCart(Integer tableId);
-
-    /**
-     * 换桌时迁移购物车
-     *
-     * @param fromTableId 原桌号ID
-     * @param toTableId   目标桌号ID
-     * @return 迁移后的购物车信息
-     */
-    CartDTO migrateCart(Integer fromTableId, Integer toTableId);
-
-    /**
-     * 检查桌号是否已使用优惠券
-     *
-     * @param tableId 桌号ID
-     * @return true-已使用, false-未使用
-     */
-    boolean hasUsedCoupon(Integer tableId);
-
-    /**
-     * 标记桌号已使用优惠券
-     *
-     * @param tableId  桌号ID
-     * @param couponId 优惠券ID
-     */
-    void markCouponUsed(Integer tableId, Integer couponId);
-
-    /**
-     * 清除桌号优惠券使用标记(换桌时使用)
-     *
-     * @param tableId 桌号ID
-     */
-    void clearCouponUsed(Integer tableId);
-
-    /**
-     * 设置用餐人数(自动添加或更新餐具)
-     *
-     * @param tableId   桌号ID
-     * @param dinerCount 用餐人数
-     * @return 购物车信息
-     */
-    CartDTO setDinerCount(Integer tableId, Integer dinerCount);
-
-    /**
-     * 更新餐具数量
-     *
-     * @param tableId 桌号ID
-     * @param quantity 餐具数量
-     * @return 购物车信息
-     */
-    CartDTO updateTablewareQuantity(Integer tableId, Integer quantity);
-
-    /**
-     * 锁定购物车商品数量(下单时调用,将当前数量锁定,不允许减少或删除)
-     *
-     * @param tableId 桌号ID
-     * @return 购物车信息
-     */
-    CartDTO lockCartItems(Integer tableId);
-
-    /**
-     * 解锁购物车商品数量(取消订单时调用,清除已下单数量,允许重新下单)
-     *
-     * @param tableId 桌号ID
-     * @return 购物车信息
-     */
-    CartDTO unlockCartItems(Integer tableId);
-}

+ 0 - 22
alien-store/src/main/java/shop/alien/store/service/DiningCollectService.java

@@ -1,22 +0,0 @@
-package shop.alien.store.service;
-
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeCollect;
-
-/**
- * 点餐模块-收藏服务(Feign 调 store 收藏接口)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/01/XX
- */
-public interface DiningCollectService {
-
-    /**
-     * 添加收藏
-     *
-     * @param lifeCollect 收藏对象
-     * @return R.data 为 Boolean(是否成功)
-     */
-    R<Boolean> addCollect(LifeCollect lifeCollect);
-}

+ 0 - 101
alien-store/src/main/java/shop/alien/store/service/DiningCouponService.java

@@ -1,101 +0,0 @@
-package shop.alien.store.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.vo.LifeDiscountCouponVo;
-
-import java.math.BigDecimal;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 点餐模块-优惠券服务(Feign 调 store 优惠券接口,供小程序使用)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/1/29
- */
-public interface DiningCouponService {
-
-    /**
-     * 获取当前用户优惠券列表(分 tab)
-     *
-     * @param authorization 请求头 Authorization,透传至 store 解析用户
-     * @param page          页码
-     * @param size          每页条数
-     * @param tabType       0:全部(未使用),1:即将过期,2:已使用,3:已过期
-     * @param type          券类型(不传:优惠券+代金券都返回,1:仅优惠券查 life_discount_coupon,4:仅代金券查 life_coupon)(可选)
-     * @param couponType    优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选,仅当type不为4时有效)
-     * @return R.data 为 List&lt;LifeDiscountCouponVo&gt;
-     */
-    R<List<LifeDiscountCouponVo>> getUserCouponList(String authorization, int page, int size, String tabType, Integer type, Integer couponType, String storeId, String storeName);
-
-    /**
-     * 根据优惠券 id 获取优惠券详情
-     *
-     * @param authorization 请求头 Authorization
-     * @param counponId     优惠券 id(与 store 接口拼写一致)
-     * @return R.data 为 LifeDiscountCouponVo
-     */
-    R<LifeDiscountCouponVo> getCounponDetailById(String authorization, String counponId);
-
-    /**
-     * 获取该门店下用户可用/不可用优惠券列表(按消费金额区分,用于选券)
-     * couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券
-     *
-     * @param authorization 请求头 Authorization
-     * @param storeId        门店 id
-     * @param amount         当前消费金额(满减门槛)
-     * @param couponType     优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)
-     * @return R.data 为 Map:canUseLifeDiscountCouponVos、forbidUseLifeDiscountCouponVos
-     */
-    R<Map<String, Object>> getStoreUserUsableCouponList(String authorization, String storeId, BigDecimal amount, Integer couponType);
-
-    /**
-     * 查询用户拥有的优惠券(按符合支付条件优先,其次优惠力度大的优先)
-     *
-     * @param storeId 门店ID(可选,如果提供则只查询该门店的优惠券)
-     * @param amount  当前消费金额(用于判断是否符合支付条件)
-     * @return 优惠券列表
-     */
-    R<List<LifeDiscountCouponVo>> getUserOwnedCoupons(String storeId, BigDecimal amount);
-
-    /**
-     * 获取该用户该店铺优惠券列表
-     * couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券
-     *
-     * @param authorization 请求头 Authorization,透传至 store 解析用户
-     * @param storeId       商户id
-     * @param couponType    优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)
-     * @return R.data 为 List&lt;LifeDiscountCouponVo&gt;
-     */
-    R<List<LifeDiscountCouponVo>> getStoreUserCouponList(String authorization, String storeId, Integer couponType);
-
-    /**
-     * 获取该店铺所有优惠券(分页), 好友优惠券
-     * couponType=1仅满减券,couponType=2仅折扣券,不传返回全部优惠券
-     *
-     * @param authorization   请求头 Authorization,透传至 store 解析用户
-     * @param page            页码(默认1)
-     * @param size            每页条数(默认10)
-     * @param storeId         商户id
-     * @param couponName      优惠券名称(可选)
-     * @param tab             分页类型(0:全部,1:进行中,2:已结束,3:草稿,4:未开始,5:已下架,6:已清库)
-     * @param couponsFromType 查询类型(1:我的优惠券,2:好友的优惠券)(默认1)
-     * @param couponStatus    优惠券状态(0:草稿,1:正式)(默认1)
-     * @param couponType      优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)
-     * @return R.data 为 IPage&lt;LifeDiscountCouponVo&gt;
-     */
-    R<IPage<LifeDiscountCouponVo>> getStoreAllCouponList(String authorization, int page, int size, String storeId,
-                                                          String couponName, String tab, int couponsFromType,
-                                                          int couponStatus, Integer couponType);
-
-    /**
-     * 查询用户目前所拥有的优惠券(可通过商铺ID进行查询)
-     *
-     * @param storeId     商铺ID(可选,如果提供则只查询该商铺的优惠券)
-     * @param couponType  优惠券类型:1=仅满减券,2=仅折扣券,不传=全部优惠券(可选)
-     * @return 优惠券列表
-     */
-    R<List<LifeDiscountCouponVo>> getUserOwnedCouponsByStore(String storeId, Integer couponType);
-}

+ 0 - 150
alien-store/src/main/java/shop/alien/store/service/DiningService.java

@@ -1,150 +0,0 @@
-package shop.alien.store.service;
-
-import shop.alien.entity.store.vo.TableDiningStatusVO;
-import shop.alien.entity.store.vo.*;
-
-import java.util.List;
-
-/**
- * 点餐服务接口
- *
- * @author system
- * @since 2025-01-XX
- */
-public interface DiningService {
-
-    /**
-     * 查询餐桌是否处于就餐中(就餐人数是否有数据),免登录可调用
-     *
-     * @param tableId 桌号ID
-     * @return 就餐状态(inDining、dinerCount)
-     */
-    TableDiningStatusVO getTableDiningStatus(Integer tableId);
-
-    /**
-     * 获取点餐页面信息
-     *
-     * @param tableId 桌号ID
-     * @param dinerCount 就餐人数
-     * @return 点餐页面信息
-     */
-    DiningPageInfoVO getDiningPageInfo(Integer tableId, Integer dinerCount);
-
-    /**
-     * 搜索菜品(模糊搜索,限10字)
-     *
-     * @param storeId 门店ID
-     * @param keyword 搜索关键词
-     * @param tableId 桌号ID(用于获取购物车数量)
-     * @return 菜品列表
-     */
-    List<CuisineListVO> searchCuisines(Integer storeId, String keyword, Integer tableId);
-
-    /**
-     * 根据分类获取菜品列表
-     *
-     * @param storeId 门店ID
-     * @param categoryId 分类ID(可为空,查询所有)
-     * @param tableId 桌号ID(用于获取购物车数量)
-     * @param page 页码(默认1)
-     * @param size 每页数量(默认12)
-     * @return 菜品列表
-     */
-    List<CuisineListVO> getCuisinesByCategory(Integer storeId, Integer categoryId, Integer tableId, Integer page, Integer size);
-
-    /**
-     * 获取菜品详情
-     *
-     * @param cuisineId 菜品ID
-     * @param tableId 桌号ID(用于获取购物车数量)
-     * @return 菜品详情
-     */
-    CuisineDetailVO getCuisineDetail(Integer cuisineId, Integer tableId);
-
-    /**
-     * 获取可领取的优惠券列表
-     *
-     * @param storeId 门店ID
-     * @param userId 用户ID
-     * @return 可领取优惠券列表
-     */
-    List<AvailableCouponVO> getAvailableCoupons(Integer storeId, Integer userId);
-
-    /**
-     * 领取优惠券
-     *
-     * @param couponId 优惠券ID
-     * @param userId 用户ID
-     * @return 是否成功
-     */
-    boolean receiveCoupon(Integer couponId, Integer userId);
-
-    /**
-     * 获取订单确认页面信息
-     *
-     * @param tableId 桌号ID
-     * @param dinerCount 就餐人数
-     * @param userId 用户ID
-     * @return 订单确认页面信息
-     */
-    OrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId);
-
-    /**
-     * 锁定订单(防止多人同时下单)
-     *
-     * @param tableId 桌号ID
-     * @param userId 用户ID
-     * @return 是否锁定成功
-     */
-    boolean lockOrder(Integer tableId, Integer userId);
-
-    /**
-     * 解锁订单
-     *
-     * @param tableId 桌号ID
-     * @param userId 用户ID
-     */
-    void unlockOrder(Integer tableId, Integer userId);
-
-    /**
-     * 检查订单是否被锁定
-     *
-     * @param tableId 桌号ID
-     * @return 锁定用户ID,如果未锁定返回null
-     */
-    Integer checkOrderLock(Integer tableId);
-
-    /**
-     * 获取订单结算确认页面信息
-     *
-     * @param orderId 订单ID
-     * @param userId 用户ID
-     * @return 订单结算确认页面信息
-     */
-    shop.alien.entity.store.vo.OrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId);
-
-    /**
-     * 锁定订单结算(防止多人同时结算)
-     *
-     * @param orderId 订单ID
-     * @param userId 用户ID
-     * @return 是否锁定成功
-     */
-    boolean lockSettlement(Integer orderId, Integer userId);
-
-    /**
-     * 解锁订单结算
-     *
-     * @param orderId 订单ID
-     * @param userId 用户ID
-     */
-    void unlockSettlement(Integer orderId, Integer userId);
-
-    /**
-     * 检查订单结算是否被锁定
-     *
-     * @param orderId 订单ID
-     * @return 锁定用户ID,如果未锁定返回null
-     */
-    Integer checkSettlementLock(Integer orderId);
-}

+ 0 - 58
alien-store/src/main/java/shop/alien/store/service/DiningUserService.java

@@ -1,58 +0,0 @@
-package shop.alien.store.service;
-
-import shop.alien.store.dto.ChangePhoneDto;
-import shop.alien.store.dto.UserProfileUpdateDto;
-import shop.alien.store.vo.DiningUserVo;
-import shop.alien.store.vo.TokenVerifyVo;
-
-/**
- * 点餐用户服务接口
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-public interface DiningUserService {
-
-    /**
-     * 微信小程序登录(标准流程:通过 code2session 获取 openid)
-     *
-     * @param code      微信登录凭证(通过 wx.login() 获取,必填)
-     * @param phoneCode 手机号凭证(通过 wx.getPhoneNumber() 获取,可选)
-     * @param macIp     客户端IP地址
-     * @return 用户信息(包含 token)
-     */
-    DiningUserVo wechatLogin(String code, String phoneCode, String macIp);
-
-    /**
-     * 更新用户个人信息
-     *
-     * @param dto 用户信息更新DTO
-     * @return 更新后的用户信息
-     */
-    DiningUserVo updateProfile(UserProfileUpdateDto dto);
-
-    /**
-     * 获取用户信息
-     *
-     * @param userId 用户ID
-     * @return 用户信息
-     */
-    DiningUserVo getUserInfo(Long userId);
-
-    /**
-     * 更换手机号:Feign 调 store 校验验证码后更新 user_phone
-     *
-     * @param dto 更换手机号请求
-     * @return 更新后的用户信息,失败返回 null
-     */
-    DiningUserVo changePhone(ChangePhoneDto dto);
-
-    /**
-     * 校验 Token 是否有效
-     *
-     * @param token Token字符串
-     * @return Token校验结果,包含用户信息和验证状态
-     */
-    TokenVerifyVo verifyToken(String token);
-}

+ 0 - 61
alien-store/src/main/java/shop/alien/store/service/OrderLockService.java

@@ -1,61 +0,0 @@
-package shop.alien.store.service;
-
-/**
- * 订单锁定服务接口
- * 用于管理订单和结算的锁定状态,防止并发操作
- *
- * @author system
- * @since 2025-01-XX
- */
-public interface OrderLockService {
-
-    /**
-     * 锁定订单(防止多人同时下单)
-     *
-     * @param tableId 桌号ID
-     * @param userId 用户ID
-     * @return 是否锁定成功
-     */
-    boolean lockOrder(Integer tableId, Integer userId);
-
-    /**
-     * 解锁订单
-     *
-     * @param tableId 桌号ID
-     * @param userId 用户ID
-     */
-    void unlockOrder(Integer tableId, Integer userId);
-
-    /**
-     * 检查订单是否被锁定
-     *
-     * @param tableId 桌号ID
-     * @return 锁定用户ID,如果未锁定返回null
-     */
-    Integer checkOrderLock(Integer tableId);
-
-    /**
-     * 锁定订单结算(防止多人同时结算)
-     *
-     * @param orderId 订单ID
-     * @param userId 用户ID
-     * @return 是否锁定成功
-     */
-    boolean lockSettlement(Integer orderId, Integer userId);
-
-    /**
-     * 解锁订单结算
-     *
-     * @param orderId 订单ID
-     * @param userId 用户ID
-     */
-    void unlockSettlement(Integer orderId, Integer userId);
-
-    /**
-     * 检查订单结算是否被锁定
-     *
-     * @param orderId 订单ID
-     * @return 锁定用户ID,如果未锁定返回null
-     */
-    Integer checkSettlementLock(Integer orderId);
-}

+ 0 - 67
alien-store/src/main/java/shop/alien/store/service/ScanOrderStoreInfoService.java

@@ -1,67 +0,0 @@
-package shop.alien.store.service;
-
-import shop.alien.entity.store.StoreCuisine;
-import shop.alien.entity.store.StoreCuisineCategory;
-import shop.alien.entity.store.StoreTable;
-import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
-import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
-
-import java.util.List;
-
-/**
- * 门店信息查询服务接口
- *
- * @author system
- * @since 2025-02-02
- */
-public interface ScanOrderStoreInfoService {
-
-    /**
-     * 根据门店ID查询桌号列表
-     *
-     * @param storeId 门店ID
-     * @return 桌号列表
-     */
-    List<StoreTable> getTablesByStoreId(Integer storeId);
-
-    /**
-     * 根据门店ID查询菜品种类列表
-     *
-     * @param storeId 门店ID
-     * @return 菜品种类列表
-     */
-    List<StoreCuisineCategory> getCategoriesByStoreId(Integer storeId);
-
-    /**
-     * 根据菜品种类ID查询菜品信息列表
-     *
-     * @param categoryId 菜品种类ID
-     * @return 菜品信息列表
-     */
-    List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId);
-
-    /**
-     * 根据门店ID查询菜品种类及每个分类下的菜品列表(一次返回种类+菜品)
-     *
-     * @param storeId 门店ID
-     * @param keyword 菜品名称模糊查询关键词(可选,为空则不按名称筛选)
-     * @return 菜品种类及下属菜品列表
-     */
-    List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword);
-
-    /**
-     * 删除菜品种类:仅逻辑删除分类并解除菜品与该分类的绑定关系,价目表(菜品)本身不改动
-     *
-     * @param categoryId 菜品种类ID
-     * @return 是否成功
-     */
-    boolean deleteCategory(Integer categoryId);
-
-    /**
-     * 根据商铺ID查询店铺信息和首页展示美食价目表信息
-     *
-     * @param storeId 商铺ID
-     * @return 店铺信息和首页展示美食价目表信息
-     */
-    StoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId);
-}

+ 0 - 35
alien-store/src/main/java/shop/alien/store/service/SseService.java

@@ -1,35 +0,0 @@
-package shop.alien.store.service;
-
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-/**
- * SSE推送服务接口
- *
- * @author system
- * @since 2025-01-XX
- */
-public interface SseService {
-
-    /**
-     * 创建SSE连接
-     *
-     * @param tableId 桌号ID
-     * @return SSE连接对象
-     */
-    SseEmitter createConnection(Integer tableId);
-
-    /**
-     * 推送购物车更新消息
-     *
-     * @param tableId 桌号ID
-     * @param message 消息内容
-     */
-    void pushCartUpdate(Integer tableId, Object message);
-
-    /**
-     * 关闭SSE连接
-     *
-     * @param tableId 桌号ID
-     */
-    void closeConnection(Integer tableId);
-}

+ 0 - 189
alien-store/src/main/java/shop/alien/store/service/StoreOrderService.java

@@ -1,189 +0,0 @@
-package shop.alien.store.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.IService;
-import shop.alien.entity.store.StoreOrder;
-import shop.alien.entity.store.dto.CreateOrderDTO;
-import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
-import shop.alien.entity.store.vo.OrderInfoVO;
-import shop.alien.entity.store.vo.StoreOrderPageVO;
-
-import java.util.List;
-
-/**
- * 订单服务接口
- *
- * @author system
- * @since 2025-01-XX
- */
-public interface StoreOrderService extends IService<StoreOrder> {
-
-    /**
-     * 创建订单
-     *
-     * @param dto 创建订单DTO
-     * @return 订单信息
-     */
-    StoreOrder createOrder(CreateOrderDTO dto);
-
-    /**
-     * 支付订单
-     *
-     * @param orderId 订单ID
-     * @param payType 支付方式
-     * @return 订单信息
-     */
-    StoreOrder payOrder(Integer orderId, Integer payType);
-
-    /**
-     * 取消订单
-     *
-     * @param orderId 订单ID
-     * @return 是否成功
-     */
-    boolean cancelOrder(Integer orderId);
-
-    /**
-     * 根据订单号查询订单
-     *
-     * @param orderNo 订单号
-     * @return 订单信息
-     */
-    StoreOrder getOrderByOrderNo(String orderNo);
-
-    /**
-     * 根据ID查询订单
-     *
-     * @param orderId 订单ID
-     * @return 订单信息
-     */
-    StoreOrder getOrderById(Integer orderId);
-
-    /**
-     * 分页查询订单列表
-     *
-     * @param page     分页参数
-     * @param storeId  门店ID
-     * @param tableId  桌号ID
-     * @param orderStatus 订单状态
-     * @param keyword  搜索关键词(订单编号或菜品名称,限15字)
-     * @return 订单分页列表
-     */
-    IPage<StoreOrder> getOrderPage(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
-
-    /**
-     * 分页查询订单列表(包含菜品信息)
-     *
-     * @param page     分页参数
-     * @param storeId  门店ID
-     * @param tableId  桌号ID
-     * @param orderStatus 订单状态
-     * @param keyword  搜索关键词(订单编号或菜品名称,限15字)
-     * @return 订单分页列表(包含菜品信息)
-     */
-    IPage<StoreOrderPageVO> getOrderPageWithCuisines(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword);
-
-    /**
-     * 完成订单(支付完成后调用)
-     *
-     * @param orderId 订单ID
-     * @return 是否成功
-     */
-    boolean completeOrder(Integer orderId);
-
-    /**
-     * 商家手动完成订单(不校验支付状态)
-     *
-     * @param orderId 订单ID
-     * @return 是否成功
-     */
-    boolean completeOrderByMerchant(Integer orderId);
-
-    /**
-     * 更新订单优惠券
-     *
-     * @param orderId 订单ID
-     * @param couponId 优惠券ID(可为空,表示不使用优惠券)
-     * @return 订单信息
-     */
-    StoreOrder updateOrderCoupon(Integer orderId, Integer couponId);
-
-    /**
-     * 管理员重置餐桌(删除购物车数据、未支付/已取消的订单数据,并重置餐桌表)
-     * 注意:已支付/已完成的订单会被保留,避免数据丢失
-     *
-     * @param tableId 餐桌ID
-     * @return 是否成功
-     */
-    boolean resetTable(Integer tableId);
-
-    /**
-     * 查询订单信息(包含订单基本信息、菜品清单、价格明细)
-     *
-     * @param orderId 订单ID
-     * @return 订单信息
-     */
-    OrderInfoVO getOrderInfo(Integer orderId);
-
-    /**
-     * 查询订单的所有变更记录(按批次分组)
-     *
-     * @param orderId 订单ID
-     * @return 变更记录批次列表
-     */
-    List<OrderChangeLogBatchVO> getOrderChangeLogs(Integer orderId);
-
-    /**
-     * 查询订单详情(包含订单基本信息和按批次分组的变更记录)
-     *
-     * @param orderId 订单ID
-     * @return 订单详情(包含变更记录)
-     */
-    shop.alien.entity.store.vo.OrderDetailWithChangeLogVO getOrderDetailWithChangeLog(Integer orderId);
-
-    /**
-     * 支付完成后重置餐桌(保留订单数据,只重置餐桌绑定关系)
-     *
-     * @param tableId 餐桌ID
-     */
-    void resetTableAfterPayment(Integer tableId);
-
-    /**
-     * 查询我的订单(通过标识查询未支付订单或历史订单)
-     *
-     * @param page 分页参数
-     * @param type 订单类型(0或"unpaid":未支付订单, 1或"history":历史订单)
-     * @return 订单分页列表
-     */
-    IPage<StoreOrder> getMyOrders(Page<StoreOrder> page, String type);
-
-    /**
-     * 查询我的订单(包含菜品信息)
-     *
-     * @param page 分页参数
-     * @param type 订单类型(0或"unpaid":未支付订单, 1或"history":历史订单)
-     * @return 订单分页列表(包含菜品信息)
-     */
-    IPage<StoreOrderPageVO> getMyOrdersWithCuisines(Page<StoreOrder> page, String type);
-
-    /**
-     * 换桌时迁移所有关联数据(订单、订单变更记录、优惠券使用记录等)
-     *
-     * @param fromTableId 原桌号ID
-     * @param toTableId   目标桌号ID
-     * @param userId      操作用户ID
-     */
-    void migrateTableData(Integer fromTableId, Integer toTableId, Integer userId);
-
-    /**
-     * 换桌(包含所有业务逻辑:迁移购物车、订单、优惠券等,记录日志,推送消息)
-     *
-     * @param fromTableId  原桌号ID
-     * @param toTableId    目标桌号ID
-     * @param changeReason 换桌原因
-     * @param userId       操作用户ID
-     * @return 迁移后的购物车信息
-     */
-    shop.alien.entity.store.dto.CartDTO changeTable(Integer fromTableId, Integer toTableId, String changeReason, Integer userId);
-}

+ 0 - 1072
alien-store/src/main/java/shop/alien/store/service/impl/CartServiceImpl.java

@@ -1,1072 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.alibaba.fastjson2.JSON;
-import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-import shop.alien.store.config.BaseRedisService;
-import shop.alien.store.service.CartService;
-import shop.alien.entity.store.StoreCart;
-import shop.alien.entity.store.StoreCouponUsage;
-import shop.alien.entity.store.StoreCuisine;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StoreTable;
-import shop.alien.entity.store.dto.AddCartItemDTO;
-import shop.alien.entity.store.dto.CartDTO;
-import shop.alien.entity.store.dto.CartItemDTO;
-import shop.alien.mapper.StoreCartMapper;
-import shop.alien.mapper.StoreCouponUsageMapper;
-import shop.alien.mapper.StoreCuisineMapper;
-import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.StoreTableMapper;
-import shop.alien.store.util.TokenUtil;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
-
-/**
- * 购物车服务实现类
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class CartServiceImpl implements CartService {
-
-    private static final String CART_KEY_PREFIX = "cart:table:";
-    private static final String COUPON_USED_KEY_PREFIX = "coupon:used:table:";
-    private static final int CART_EXPIRE_SECONDS = 24 * 60 * 60; // 24小时过期
-
-    // 异步写入数据库的线程池(专门用于购物车数据库写入)
-    private static final ExecutorService CART_DB_WRITE_EXECUTOR = Executors.newFixedThreadPool(5, r -> {
-        Thread t = new Thread(r, "cart-db-write-" + System.currentTimeMillis());
-        t.setDaemon(true);
-        return t;
-    });
-
-    private final BaseRedisService baseRedisService;
-    private final StoreTableMapper storeTableMapper;
-    private final StoreCuisineMapper storeCuisineMapper;
-    private final StoreCartMapper storeCartMapper;
-    private final StoreCouponUsageMapper storeCouponUsageMapper;
-    private final StoreInfoMapper storeInfoMapper;
-
-    @Override
-    public CartDTO getCart(Integer tableId) {
-        log.info("获取购物车, tableId={}", tableId);
-        String cartKey = CART_KEY_PREFIX + tableId;
-        String cartJson = baseRedisService.getString(cartKey);
-
-        CartDTO cart = new CartDTO();
-        cart.setTableId(tableId);
-
-        // 查询桌号信息
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            cart.setTableNumber(table.getTableNumber());
-            cart.setStoreId(table.getStoreId());
-        }
-
-        if (StringUtils.hasText(cartJson)) {
-            try {
-                JSONObject cartObj = JSON.parseObject(cartJson);
-                List<CartItemDTO> items = cartObj.getList("items", CartItemDTO.class);
-                if (items != null) {
-                    cart.setItems(items);
-                    // 计算总金额和总数量
-                    BigDecimal totalAmount = items.stream()
-                            .map(CartItemDTO::getSubtotalAmount)
-                            .reduce(BigDecimal.ZERO, BigDecimal::add);
-                    Integer totalQuantity = items.stream()
-                            .mapToInt(CartItemDTO::getQuantity)
-                            .sum();
-                    cart.setTotalAmount(totalAmount);
-                    cart.setTotalQuantity(totalQuantity);
-                } else {
-                    cart.setItems(new ArrayList<>());
-                    cart.setTotalAmount(BigDecimal.ZERO);
-                    cart.setTotalQuantity(0);
-                }
-            } catch (Exception e) {
-                log.error("解析购物车数据失败: {}", e.getMessage(), e);
-                cart.setItems(new ArrayList<>());
-                cart.setTotalAmount(BigDecimal.ZERO);
-                cart.setTotalQuantity(0);
-            }
-        } else {
-            // Redis中没有,尝试从数据库加载
-            cart = loadCartFromDatabase(tableId);
-        }
-
-        return cart;
-    }
-
-    /**
-     * 从数据库加载购物车
-     */
-    private CartDTO loadCartFromDatabase(Integer tableId) {
-        log.info("从数据库加载购物车, tableId={}", tableId);
-        CartDTO cart = new CartDTO();
-        cart.setTableId(tableId);
-        cart.setItems(new ArrayList<>());
-        cart.setTotalAmount(BigDecimal.ZERO);
-        cart.setTotalQuantity(0);
-
-        // 查询桌号信息
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            cart.setTableNumber(table.getTableNumber());
-            cart.setStoreId(table.getStoreId());
-        }
-
-        // 从数据库查询购物车数据
-        LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCart::getTableId, tableId);
-        wrapper.eq(StoreCart::getDeleteFlag, 0);
-        List<StoreCart> cartList = storeCartMapper.selectList(wrapper);
-
-        if (cartList != null && !cartList.isEmpty()) {
-            List<CartItemDTO> items = cartList.stream().map(cartItem -> {
-                CartItemDTO item = new CartItemDTO();
-                item.setCuisineId(cartItem.getCuisineId());
-                item.setCuisineName(cartItem.getCuisineName());
-                item.setCuisineImage(cartItem.getCuisineImage());
-                item.setUnitPrice(cartItem.getUnitPrice());
-                item.setQuantity(cartItem.getQuantity());
-                item.setLockedQuantity(cartItem.getLockedQuantity());
-                item.setSubtotalAmount(cartItem.getSubtotalAmount());
-                item.setAddUserId(cartItem.getAddUserId());
-                item.setAddUserPhone(cartItem.getAddUserPhone());
-                item.setRemark(cartItem.getRemark());
-                return item;
-            }).collect(Collectors.toList());
-
-            cart.setItems(items);
-            BigDecimal totalAmount = items.stream()
-                    .map(CartItemDTO::getSubtotalAmount)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-            Integer totalQuantity = items.stream()
-                    .mapToInt(CartItemDTO::getQuantity)
-                    .sum();
-            cart.setTotalAmount(totalAmount);
-            cart.setTotalQuantity(totalQuantity);
-
-            // 同步到Redis
-            saveCartToRedis(cart);
-        }
-
-        return cart;
-    }
-
-    @Override
-    public CartDTO addItem(AddCartItemDTO dto) {
-        log.info("添加商品到购物车, dto={}", dto);
-        // 验证桌号
-        StoreTable table = storeTableMapper.selectById(dto.getTableId());
-        if (table == null) {
-            throw new RuntimeException("桌号不存在");
-        }
-
-        // 验证菜品
-        StoreCuisine cuisine = storeCuisineMapper.selectById(dto.getCuisineId());
-        if (cuisine == null) {
-            throw new RuntimeException("菜品不存在");
-        }
-        if (cuisine.getShelfStatus() != 1) {
-            throw new RuntimeException("菜品已下架");
-        }
-
-        // 获取当前用户信息
-        Integer userId = TokenUtil.getCurrentUserId();
-        String userPhone = TokenUtil.getCurrentUserPhone();
-
-        // 获取购物车
-        CartDTO cart = getCart(dto.getTableId());
-
-        // 查找是否已存在该商品
-        List<CartItemDTO> items = cart.getItems();
-        CartItemDTO existingItem = items.stream()
-                .filter(item -> item.getCuisineId().equals(dto.getCuisineId()))
-                .findFirst()
-                .orElse(null);
-
-        if (existingItem != null) {
-            // 商品已存在
-            Integer lockedQuantity = existingItem.getLockedQuantity();
-            if (lockedQuantity != null && lockedQuantity > 0) {
-                // 如果商品有已下单数量,将新数量叠加到当前数量和已下单数量上
-                Integer newQuantity = existingItem.getQuantity() + dto.getQuantity();
-                Integer newLockedQuantity = lockedQuantity + dto.getQuantity();
-                existingItem.setQuantity(newQuantity);
-                existingItem.setLockedQuantity(newLockedQuantity);
-                existingItem.setSubtotalAmount(existingItem.getUnitPrice()
-                        .multiply(BigDecimal.valueOf(newQuantity)));
-                log.info("商品已存在且有已下单数量,叠加数量, cuisineId={}, oldQuantity={}, newQuantity={}, oldOrderedQuantity={}, newOrderedQuantity={}", 
-                        dto.getCuisineId(), existingItem.getQuantity() - dto.getQuantity(), newQuantity, lockedQuantity, newLockedQuantity);
-            } else {
-                // 商品已存在但没有已下单数量,不允许重复添加
-                throw new RuntimeException("已添加过本商品");
-            }
-        } else {
-            // 添加新商品
-            CartItemDTO newItem = new CartItemDTO();
-            newItem.setCuisineId(cuisine.getId());
-            newItem.setCuisineName(cuisine.getName());
-            newItem.setCuisineType(cuisine.getCuisineType());
-            newItem.setCuisineImage(cuisine.getImages());
-            newItem.setUnitPrice(cuisine.getTotalPrice());
-            newItem.setQuantity(dto.getQuantity());
-            newItem.setSubtotalAmount(cuisine.getTotalPrice()
-                    .multiply(BigDecimal.valueOf(dto.getQuantity())));
-            newItem.setAddUserId(userId);
-            newItem.setAddUserPhone(userPhone);
-            newItem.setRemark(dto.getRemark());
-            items.add(newItem);
-        }
-
-        // 重新计算总金额和总数量
-        BigDecimal totalAmount = items.stream()
-                .map(CartItemDTO::getSubtotalAmount)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        Integer totalQuantity = items.stream()
-                .mapToInt(CartItemDTO::getQuantity)
-                .sum();
-        cart.setTotalAmount(totalAmount);
-        cart.setTotalQuantity(totalQuantity);
-
-        // 保存到Redis和数据库(双写策略)
-        saveCart(cart);
-
-        return cart;
-    }
-
-    @Override
-    public CartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity) {
-        log.info("更新购物车商品数量, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
-        
-        // 如果数量为0或小于0,删除该商品
-        if (quantity == null || quantity <= 0) {
-            log.info("商品数量为0或小于0,删除商品, tableId={}, cuisineId={}", tableId, cuisineId);
-            return removeItem(tableId, cuisineId);
-        }
-
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-        CartItemDTO item = items.stream()
-                .filter(i -> i.getCuisineId().equals(cuisineId))
-                .findFirst()
-                .orElse(null);
-
-        if (item != null) {
-            // 商品已存在,更新数量
-            // 检查已下单数量:不允许将数量减少到小于已下单数量
-            Integer lockedQuantity = item.getLockedQuantity();
-            if (lockedQuantity != null && lockedQuantity > 0) {
-                if (quantity < lockedQuantity) {
-                    throw new RuntimeException("商品数量不能少于已下单数量(" + lockedQuantity + "),该数量已下单");
-                }
-            }
-            
-            item.setQuantity(quantity);
-            item.setSubtotalAmount(item.getUnitPrice()
-                    .multiply(BigDecimal.valueOf(quantity)));
-
-            // 重新计算总金额和总数量
-            BigDecimal totalAmount = items.stream()
-                    .map(CartItemDTO::getSubtotalAmount)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-            Integer totalQuantity = items.stream()
-                    .mapToInt(CartItemDTO::getQuantity)
-                    .sum();
-            cart.setTotalAmount(totalAmount);
-            cart.setTotalQuantity(totalQuantity);
-
-            saveCart(cart);
-        } else {
-            // 商品不存在,自动添加
-            log.info("商品不在购物车中,自动添加, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
-            
-            // 验证菜品
-            StoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
-            if (cuisine == null) {
-                throw new RuntimeException("菜品不存在");
-            }
-            if (cuisine.getShelfStatus() != 1) {
-                throw new RuntimeException("菜品已下架");
-            }
-
-            // 获取当前用户信息
-            Integer userId = TokenUtil.getCurrentUserId();
-            String userPhone = TokenUtil.getCurrentUserPhone();
-
-            // 创建新的购物车商品项
-            CartItemDTO newItem = new CartItemDTO();
-            newItem.setCuisineId(cuisine.getId());
-            newItem.setCuisineName(cuisine.getName());
-            newItem.setCuisineType(cuisine.getCuisineType());
-            newItem.setCuisineImage(cuisine.getImages());
-            newItem.setUnitPrice(cuisine.getTotalPrice());
-            newItem.setQuantity(quantity);
-            newItem.setSubtotalAmount(cuisine.getTotalPrice()
-                    .multiply(BigDecimal.valueOf(quantity)));
-            newItem.setAddUserId(userId);
-            newItem.setAddUserPhone(userPhone);
-            items.add(newItem);
-
-            // 重新计算总金额和总数量
-            BigDecimal totalAmount = items.stream()
-                    .map(CartItemDTO::getSubtotalAmount)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-            Integer totalQuantity = items.stream()
-                    .mapToInt(CartItemDTO::getQuantity)
-                    .sum();
-            cart.setTotalAmount(totalAmount);
-            cart.setTotalQuantity(totalQuantity);
-
-            // 保存到Redis和数据库(双写策略)
-            saveCart(cart);
-            log.info("商品已自动添加到购物车, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
-        }
-
-        return cart;
-    }
-
-    @Override
-    public CartDTO removeItem(Integer tableId, Integer cuisineId) {
-        log.info("删除购物车商品, tableId={}, cuisineId={}", tableId, cuisineId);
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-        
-        // 检查是否有已下单数量,如果有则不允许删除
-        CartItemDTO item = items.stream()
-                .filter(i -> i.getCuisineId().equals(cuisineId))
-                .findFirst()
-                .orElse(null);
-        
-        if (item != null) {
-            Integer lockedQuantity = item.getLockedQuantity();
-            if (lockedQuantity != null && lockedQuantity > 0) {
-                throw new RuntimeException("商品已下单,已下单数量为 " + lockedQuantity + ",不允许删除");
-            }
-        }
-        
-        items.removeIf(i -> i.getCuisineId().equals(cuisineId));
-
-        // 重新计算总金额和总数量
-        BigDecimal totalAmount = items.stream()
-                .map(CartItemDTO::getSubtotalAmount)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        Integer totalQuantity = items.stream()
-                .mapToInt(CartItemDTO::getQuantity)
-                .sum();
-        cart.setTotalAmount(totalAmount);
-        cart.setTotalQuantity(totalQuantity);
-
-        saveCart(cart);
-        return cart;
-    }
-
-    @Override
-    public void clearCart(Integer tableId) {
-        log.info("清空购物车(保留已下单商品), tableId={}", tableId);
-        
-        // 获取购物车
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-        
-        if (items == null || items.isEmpty()) {
-            log.info("购物车为空,无需清空, tableId={}", tableId);
-            return;
-        }
-        
-        // 分离已下单的商品、未下单的商品和餐具
-        List<CartItemDTO> orderedItems = new ArrayList<>(); // 已下单的商品(保留,数量恢复为已下单数量)
-        List<Integer> orderedCuisineIds = new ArrayList<>(); // 已下单的商品ID列表
-        List<CartItemDTO> unorderedItems = new ArrayList<>(); // 未下单的商品(删除)
-        CartItemDTO tablewareItem = null; // 餐具项(始终保留)
-        boolean hasChanges = false; // 是否有变化(需要更新)
-        
-        for (CartItemDTO item : items) {
-            // 餐具始终保留,不清空
-            if (TABLEWARE_CUISINE_ID.equals(item.getCuisineId())) {
-                tablewareItem = item;
-                continue;
-            }
-            
-            Integer lockedQuantity = item.getLockedQuantity();
-            if (lockedQuantity != null && lockedQuantity > 0) {
-                // 有已下单数量,保留该商品,但将当前数量恢复为已下单数量
-                Integer currentQuantity = item.getQuantity();
-                if (currentQuantity != null && !currentQuantity.equals(lockedQuantity)) {
-                    // 当前数量不等于已下单数量,需要恢复
-                    item.setQuantity(lockedQuantity);
-                    item.setSubtotalAmount(item.getUnitPrice().multiply(BigDecimal.valueOf(lockedQuantity)));
-                    hasChanges = true;
-                    log.info("恢复已下单商品数量, cuisineId={}, oldQuantity={}, orderedQuantity={}", 
-                            item.getCuisineId(), currentQuantity, lockedQuantity);
-                }
-                orderedItems.add(item);
-                orderedCuisineIds.add(item.getCuisineId());
-            } else {
-                // 没有已下单数量,标记为删除
-                unorderedItems.add(item);
-                hasChanges = true;
-            }
-        }
-        
-        // 将餐具项添加到保留列表中,若有已下单数量则恢复为已下单数量(与菜品逻辑一致)
-        if (tablewareItem != null) {
-            Integer tablewareLocked = tablewareItem.getLockedQuantity();
-            if (tablewareLocked != null && tablewareLocked > 0) {
-                Integer currentQty = tablewareItem.getQuantity();
-                if (currentQty == null || !currentQty.equals(tablewareLocked)) {
-                    tablewareItem.setQuantity(tablewareLocked);
-                    tablewareItem.setSubtotalAmount(tablewareItem.getUnitPrice().multiply(BigDecimal.valueOf(tablewareLocked)));
-                    hasChanges = true;
-                    log.info("恢复餐具数量为已下单数量, cuisineId={}, oldQuantity={}, orderedQuantity={}",
-                            tablewareItem.getCuisineId(), currentQty, tablewareLocked);
-                }
-            }
-            orderedItems.add(tablewareItem);
-            orderedCuisineIds.add(tablewareItem.getCuisineId());
-            log.info("保留餐具项, cuisineId={}, quantity={}", tablewareItem.getCuisineId(), tablewareItem.getQuantity());
-        }
-        
-        // 如果有变化(有未下单的商品需要删除,或者已下单商品数量需要恢复),进行更新
-        if (hasChanges) {
-            // 1. 更新购物车(删除未下单商品,已下单商品数量已恢复)
-            cart.setItems(orderedItems);
-            // 重新计算总金额和总数量(只计算保留的商品,数量已恢复为已下单数量)
-            BigDecimal totalAmount = orderedItems.stream()
-                    .map(CartItemDTO::getSubtotalAmount)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-            Integer totalQuantity = orderedItems.stream()
-                    .mapToInt(CartItemDTO::getQuantity)
-                    .sum();
-            cart.setTotalAmount(totalAmount);
-            cart.setTotalQuantity(totalQuantity);
-            
-            // 更新Redis(保留已下单的商品,数量已恢复)
-            if (orderedItems.isEmpty()) {
-                // 如果所有商品都未下单,清空Redis
-                String cartKey = CART_KEY_PREFIX + tableId;
-                baseRedisService.delete(cartKey);
-            } else {
-                // 保存更新后的购物车到Redis(已下单商品数量已恢复为已下单数量)
-                saveCartToRedis(cart);
-            }
-            
-            // 2. 从数据库中逻辑删除未下单的商品(排除餐具)
-            if (!unorderedItems.isEmpty()) {
-                LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
-                wrapper.eq(StoreCart::getTableId, tableId);
-                wrapper.eq(StoreCart::getDeleteFlag, 0);
-                // 排除餐具(cuisineId = -1)
-                wrapper.ne(StoreCart::getCuisineId, TABLEWARE_CUISINE_ID);
-                if (!orderedCuisineIds.isEmpty()) {
-                    // 排除已下单的商品ID(包括餐具)
-                    wrapper.notIn(StoreCart::getCuisineId, orderedCuisineIds);
-                }
-                List<StoreCart> cartListToDelete = storeCartMapper.selectList(wrapper);
-                if (cartListToDelete != null && !cartListToDelete.isEmpty()) {
-                    List<Integer> cartIds = cartListToDelete.stream()
-                            .map(StoreCart::getId)
-                            .collect(Collectors.toList());
-                    // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-                    storeCartMapper.deleteBatchIds(cartIds);
-                    log.info("删除未下单商品(已排除餐具), tableId={}, count={}", tableId, cartIds.size());
-                }
-            }
-            
-            // 3. 更新数据库中已下单商品的数量(恢复为已下单数量)
-            if (!orderedItems.isEmpty()) {
-                // 保存更新后的购物车到数据库(会更新已下单商品的数量)
-                saveCartToDatabase(cart);
-            }
-            
-            // 4. 更新桌号表的购物车统计
-            StoreTable table = storeTableMapper.selectById(tableId);
-            if (table != null) {
-                table.setCartItemCount(totalQuantity);
-                table.setCartTotalAmount(totalAmount);
-                storeTableMapper.updateById(table);
-            }
-            
-            log.info("清空购物车完成(保留已下单商品和餐具,数量恢复为已下单数量), tableId={}, 删除商品数={}, 保留商品数={}", 
-                    tableId, unorderedItems.size(), orderedItems.size());
-        } else {
-            log.info("购物车无需更新, tableId={}", tableId);
-        }
-    }
-
-    @Override
-    public CartDTO migrateCart(Integer fromTableId, Integer toTableId) {
-        log.info("迁移购物车, fromTableId={}, toTableId={}", fromTableId, toTableId);
-        // 获取原购物车
-        CartDTO fromCart = getCart(fromTableId);
-
-        // 验证目标桌号
-        StoreTable toTable = storeTableMapper.selectById(toTableId);
-        if (toTable == null) {
-            throw new RuntimeException("目标桌号不存在");
-        }
-
-        // 获取目标购物车
-        CartDTO toCart = getCart(toTableId);
-
-        // 合并购物车(如果目标桌号已有商品,则合并)
-        List<CartItemDTO> mergedItems = new ArrayList<>(toCart.getItems());
-        for (CartItemDTO fromItem : fromCart.getItems()) {
-            CartItemDTO existingItem = mergedItems.stream()
-                    .filter(item -> item.getCuisineId().equals(fromItem.getCuisineId()))
-                    .findFirst()
-                    .orElse(null);
-
-            if (existingItem != null) {
-                // 合并数量
-                int newQuantity = (existingItem.getQuantity() != null ? existingItem.getQuantity() : 0)
-                        + (fromItem.getQuantity() != null ? fromItem.getQuantity() : 0);
-                existingItem.setQuantity(newQuantity);
-                existingItem.setSubtotalAmount(existingItem.getUnitPrice()
-                        .multiply(BigDecimal.valueOf(newQuantity)));
-                // 合并已下单数量(换桌后目标桌需保留两边的已下单数量)
-                int toLocked = existingItem.getLockedQuantity() != null ? existingItem.getLockedQuantity() : 0;
-                int fromLocked = fromItem.getLockedQuantity() != null ? fromItem.getLockedQuantity() : 0;
-                existingItem.setLockedQuantity(toLocked + fromLocked > 0 ? toLocked + fromLocked : null);
-            } else {
-                mergedItems.add(fromItem);
-            }
-        }
-
-        toCart.setItems(mergedItems);
-        toCart.setTableId(toTableId);
-        toCart.setTableNumber(toTable.getTableNumber());
-        toCart.setStoreId(toTable.getStoreId());
-
-        // 重新计算总金额和总数量
-        BigDecimal totalAmount = mergedItems.stream()
-                .map(CartItemDTO::getSubtotalAmount)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        Integer totalQuantity = mergedItems.stream()
-                .mapToInt(CartItemDTO::getQuantity)
-                .sum();
-        toCart.setTotalAmount(totalAmount);
-        toCart.setTotalQuantity(totalQuantity);
-
-        // 保存目标购物车
-        saveCart(toCart);
-
-        // 清空原购物车
-        clearCart(fromTableId);
-
-        // 迁移优惠券使用标记
-        if (hasUsedCoupon(fromTableId)) {
-            String couponUsedKey = COUPON_USED_KEY_PREFIX + fromTableId;
-            String couponId = baseRedisService.getString(couponUsedKey);
-            if (StringUtils.hasText(couponId)) {
-                markCouponUsed(toTableId, Integer.parseInt(couponId));
-                clearCouponUsed(fromTableId);
-            }
-        }
-
-        return toCart;
-    }
-
-    @Override
-    public boolean hasUsedCoupon(Integer tableId) {
-        // 先查Redis
-        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
-        String couponId = baseRedisService.getString(couponUsedKey);
-        if (StringUtils.hasText(couponId)) {
-            return true;
-        }
-
-        // Redis中没有,查数据库
-        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCouponUsage::getTableId, tableId);
-        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-        wrapper.in(StoreCouponUsage::getUsageStatus, 0, 1, 2); // 已标记使用、已下单、已支付
-        wrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-        wrapper.last("LIMIT 1");
-        StoreCouponUsage usage = storeCouponUsageMapper.selectOne(wrapper);
-        return usage != null;
-    }
-
-    @Override
-    public void markCouponUsed(Integer tableId, Integer couponId) {
-        // 保存到Redis
-        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
-        baseRedisService.setString(couponUsedKey, String.valueOf(couponId), (long) CART_EXPIRE_SECONDS);
-
-        // 保存到数据库
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table == null) {
-            log.warn("桌号不存在, tableId={}", tableId);
-            return;
-        }
-
-        // 检查是否已存在
-        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCouponUsage::getTableId, tableId);
-        wrapper.eq(StoreCouponUsage::getCouponId, couponId);
-        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-        StoreCouponUsage existing = storeCouponUsageMapper.selectOne(wrapper);
-
-        if (existing == null) {
-            Date now = new Date();
-            StoreCouponUsage usage = new StoreCouponUsage();
-            usage.setTableId(tableId);
-            usage.setStoreId(table.getStoreId());
-            usage.setCouponId(couponId);
-            usage.setUsageStatus(0); // 已标记使用
-            usage.setCreatedTime(now);
-            usage.setUpdatedTime(now); // 设置更新时间,避免数据库约束错误
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId != null) {
-                usage.setCreatedUserId(userId);
-            }
-            storeCouponUsageMapper.insert(usage);
-        }
-
-        // 更新桌号表的优惠券ID
-        table.setCurrentCouponId(couponId);
-        storeTableMapper.updateById(table);
-    }
-
-    @Override
-    public void clearCouponUsed(Integer tableId) {
-        // 清空Redis
-        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
-        baseRedisService.delete(couponUsedKey);
-
-        // 更新数据库(逻辑删除未下单的记录,使用 MyBatis-Plus 的 deleteBatchIds)
-        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCouponUsage::getTableId, tableId);
-        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-        wrapper.eq(StoreCouponUsage::getUsageStatus, 0); // 只删除已标记使用但未下单的
-        List<StoreCouponUsage> usageList = storeCouponUsageMapper.selectList(wrapper);
-        if (usageList != null && !usageList.isEmpty()) {
-            List<Integer> usageIds = usageList.stream()
-                    .map(StoreCouponUsage::getId)
-                    .collect(Collectors.toList());
-            // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-            storeCouponUsageMapper.deleteBatchIds(usageIds);
-        }
-
-        // 更新桌号表的优惠券ID
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            table.setCurrentCouponId(null);
-            storeTableMapper.updateById(table);
-        }
-    }
-
-    /**
-     * 餐具的特殊ID(用于标识餐具项)
-     */
-    private static final Integer TABLEWARE_CUISINE_ID = -1;
-    private static final String TABLEWARE_NAME = "餐具费";
-
-    /**
-     * 获取餐具单价(从 store_info 表获取)
-     *
-     * @param storeId 门店ID
-     * @return 餐具单价(BigDecimal),如果门店不存在或未设置餐具费,返回 0.00
-     */
-    private BigDecimal getTablewareUnitPrice(Integer storeId) {
-        if (storeId == null) {
-            log.warn("门店ID为空,返回默认餐具单价 0.00");
-            return BigDecimal.ZERO;
-        }
-        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
-        if (storeInfo == null) {
-            log.warn("门店不存在, storeId={},返回默认餐具单价 0.00", storeId);
-            return BigDecimal.ZERO;
-        }
-        Integer tablewareFee = storeInfo.getTablewareFee();
-        if (tablewareFee == null || tablewareFee < 0) {
-            log.warn("门店餐具费未设置或无效, storeId={}, tablewareFee={},返回默认餐具单价 0.00", storeId, tablewareFee);
-            return BigDecimal.ZERO;
-        }
-        return BigDecimal.valueOf(tablewareFee);
-    }
-
-    @Override
-    public CartDTO setDinerCount(Integer tableId, Integer dinerCount) {
-        log.info("设置用餐人数, tableId={}, dinerCount={}", tableId, dinerCount);
-        
-        if (dinerCount == null || dinerCount <= 0) {
-            throw new RuntimeException("用餐人数必须大于0");
-        }
-
-        // 获取购物车
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-
-        // 获取门店ID和餐具单价
-        Integer storeId = cart.getStoreId();
-        if (storeId == null) {
-            // 如果购物车中没有门店ID,从桌号获取
-            StoreTable table = storeTableMapper.selectById(tableId);
-            if (table != null) {
-                storeId = table.getStoreId();
-            }
-        }
-        BigDecimal tablewareUnitPrice = getTablewareUnitPrice(storeId);
-
-        // 商铺未设置餐具费时,不往购物车加餐具;若已有餐具项则移除
-        if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
-            log.info("门店未设置餐具费, storeId={},设置就餐人数时不添加餐具", storeId);
-            CartItemDTO existing = items.stream()
-                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
-                    .findFirst()
-                    .orElse(null);
-            if (existing != null) {
-                items.remove(existing);
-            }
-        } else {
-            // 查找是否已存在餐具项
-            CartItemDTO tablewareItem = items.stream()
-                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
-                    .findFirst()
-                    .orElse(null);
-
-            Integer userId = TokenUtil.getCurrentUserId();
-            String userPhone = TokenUtil.getCurrentUserPhone();
-
-            if (tablewareItem != null) {
-                Integer lockedQuantity = tablewareItem.getLockedQuantity();
-                if (lockedQuantity != null && lockedQuantity > 0 && dinerCount < lockedQuantity) {
-                    throw new RuntimeException("餐具数量不能少于已下单数量(" + lockedQuantity + ")");
-                }
-                tablewareItem.setQuantity(dinerCount);
-                tablewareItem.setUnitPrice(tablewareUnitPrice);
-                tablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(dinerCount)));
-            } else {
-                CartItemDTO newTablewareItem = new CartItemDTO();
-                newTablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
-                newTablewareItem.setCuisineName(TABLEWARE_NAME);
-                newTablewareItem.setCuisineType(0);
-                newTablewareItem.setCuisineImage("");
-                newTablewareItem.setUnitPrice(tablewareUnitPrice);
-                newTablewareItem.setQuantity(dinerCount);
-                newTablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(dinerCount)));
-                newTablewareItem.setAddUserId(userId);
-                newTablewareItem.setAddUserPhone(userPhone);
-                items.add(newTablewareItem);
-            }
-        }
-
-        // 重新计算总金额和总数量
-        BigDecimal totalAmount = items.stream()
-                .map(CartItemDTO::getSubtotalAmount)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        Integer totalQuantity = items.stream()
-                .mapToInt(CartItemDTO::getQuantity)
-                .sum();
-        cart.setTotalAmount(totalAmount);
-        cart.setTotalQuantity(totalQuantity);
-
-        // 保存到Redis和数据库(双写策略)
-        saveCart(cart);
-
-        return cart;
-    }
-
-    @Override
-    public CartDTO updateTablewareQuantity(Integer tableId, Integer quantity) {
-        log.info("更新餐具数量, tableId={}, quantity={}", tableId, quantity);
-        
-        if (quantity == null || quantity < 0) {
-            throw new RuntimeException("餐具数量不能小于0");
-        }
-
-        if (quantity == 0) {
-            // 数量为0时,删除餐具项
-            return removeItem(tableId, TABLEWARE_CUISINE_ID);
-        }
-
-        // 获取购物车
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-
-        // 获取门店ID和餐具单价
-        Integer storeId = cart.getStoreId();
-        if (storeId == null) {
-            StoreTable table = storeTableMapper.selectById(tableId);
-            if (table != null) {
-                storeId = table.getStoreId();
-            }
-        }
-        BigDecimal tablewareUnitPrice = getTablewareUnitPrice(storeId);
-
-        // 商铺未设置餐具费(单价为0或未配置)时,不往购物车加餐具;若已有餐具项则移除
-        if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
-            log.info("门店未设置餐具费, storeId={},不添加餐具到购物车", storeId);
-            CartItemDTO existing = items.stream()
-                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
-                    .findFirst()
-                    .orElse(null);
-            if (existing != null) {
-                items.remove(existing);
-                BigDecimal totalAmount = items.stream()
-                        .map(CartItemDTO::getSubtotalAmount)
-                        .reduce(BigDecimal.ZERO, BigDecimal::add);
-                Integer totalQuantity = items.stream()
-                        .mapToInt(CartItemDTO::getQuantity)
-                        .sum();
-                cart.setTotalAmount(totalAmount);
-                cart.setTotalQuantity(totalQuantity);
-                saveCart(cart);
-            }
-            return cart;
-        }
-
-        // 查找餐具项
-        CartItemDTO tablewareItem = items.stream()
-                .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
-                .findFirst()
-                .orElse(null);
-
-        if (tablewareItem == null) {
-            // 如果不存在餐具项,创建一个
-            Integer userId = TokenUtil.getCurrentUserId();
-            String userPhone = TokenUtil.getCurrentUserPhone();
-            
-            tablewareItem = new CartItemDTO();
-            tablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
-            tablewareItem.setCuisineName(TABLEWARE_NAME);
-            tablewareItem.setCuisineType(0); // 0表示餐具
-            tablewareItem.setCuisineImage("");
-            tablewareItem.setUnitPrice(tablewareUnitPrice);
-            tablewareItem.setAddUserId(userId);
-            tablewareItem.setAddUserPhone(userPhone);
-            items.add(tablewareItem);
-        } else {
-            // 下单后只能增不能减:已有已下单数量时,数量不能少于已下单数量
-            Integer lockedQuantity = tablewareItem.getLockedQuantity();
-            if (lockedQuantity != null && lockedQuantity > 0 && quantity < lockedQuantity) {
-                throw new RuntimeException("餐具数量不能少于已下单数量(" + lockedQuantity + ")");
-            }
-            // 如果已存在,更新单价(可能门店修改了餐具费)
-            tablewareItem.setUnitPrice(tablewareUnitPrice);
-        }
-
-        // 更新数量
-        tablewareItem.setQuantity(quantity);
-        tablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(quantity)));
-
-        // 重新计算总金额和总数量
-        BigDecimal totalAmount = items.stream()
-                .map(CartItemDTO::getSubtotalAmount)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
-        Integer totalQuantity = items.stream()
-                .mapToInt(CartItemDTO::getQuantity)
-                .sum();
-        cart.setTotalAmount(totalAmount);
-        cart.setTotalQuantity(totalQuantity);
-
-        // 保存到Redis和数据库(双写策略)
-        saveCart(cart);
-
-        return cart;
-    }
-
-    @Override
-    public CartDTO lockCartItems(Integer tableId) {
-        log.info("锁定购物车商品数量(设置已下单数量), tableId={}", tableId);
-        
-        // 获取购物车
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-        
-        if (items == null || items.isEmpty()) {
-            log.warn("购物车为空,无需锁定, tableId={}", tableId);
-            return cart;
-        }
-        
-        // 遍历所有商品,将当前数量设置为已下单数量
-        boolean hasChanges = false;
-        for (CartItemDTO item : items) {
-            Integer currentQuantity = item.getQuantity();
-            Integer lockedQuantity = item.getLockedQuantity();
-            
-            if (currentQuantity != null && currentQuantity > 0) {
-                if (lockedQuantity == null || lockedQuantity == 0) {
-                    // 如果还没有已下单数量,将当前数量设置为已下单数量
-                    item.setLockedQuantity(currentQuantity);
-                    hasChanges = true;
-                    log.info("设置商品已下单数量, cuisineId={}, orderedQuantity={}", item.getCuisineId(), currentQuantity);
-                } else if (currentQuantity > lockedQuantity) {
-                    // 如果已有已下单数量,且当前数量大于已下单数量(再次下单的情况),将新增数量累加到已下单数量
-                    Integer newLockedQuantity = lockedQuantity + (currentQuantity - lockedQuantity);
-                    item.setLockedQuantity(newLockedQuantity);
-                    hasChanges = true;
-                    log.info("更新商品已下单数量, cuisineId={}, oldOrderedQuantity={}, newOrderedQuantity={}", 
-                            item.getCuisineId(), lockedQuantity, newLockedQuantity);
-                }
-            }
-        }
-        
-        // 如果有变化,保存购物车
-        if (hasChanges) {
-            saveCart(cart);
-        }
-        
-        return cart;
-    }
-
-    @Override
-    public CartDTO unlockCartItems(Integer tableId) {
-        log.info("解锁购物车商品数量(清除已下单数量), tableId={}", tableId);
-        
-        // 获取购物车
-        CartDTO cart = getCart(tableId);
-        List<CartItemDTO> items = cart.getItems();
-        
-        if (items == null || items.isEmpty()) {
-            log.info("购物车为空,无需解锁, tableId={}", tableId);
-            return cart;
-        }
-        
-        // 遍历所有商品,清除已下单数量(lockedQuantity)
-        boolean hasChanges = false;
-        for (CartItemDTO item : items) {
-            if (item.getLockedQuantity() != null && item.getLockedQuantity() > 0) {
-                // 清除已下单数量,允许重新下单
-                item.setLockedQuantity(null);
-                hasChanges = true;
-                log.info("清除商品已下单数量, cuisineId={}", item.getCuisineId());
-            }
-        }
-        
-        // 如果有变化,保存购物车
-        if (hasChanges) {
-            saveCart(cart);
-            log.info("解锁购物车商品数量完成, tableId={}", tableId);
-        } else {
-            log.info("购物车无需解锁, tableId={}", tableId);
-        }
-        
-        return cart;
-    }
-
-    /**
-     * 保存购物车到Redis和数据库(优化后的双写策略)
-     * Redis同步写入(保证实时性),数据库异步批量写入(提高性能)
-     */
-    private void saveCart(CartDTO cart) {
-        // 1. 同步保存到Redis(保证实时性)
-        saveCartToRedis(cart);
-
-        // 2. 异步保存到数据库(不阻塞主流程,提高性能)
-        CompletableFuture.runAsync(() -> {
-            try {
-                saveCartToDatabase(cart);
-            } catch (Exception e) {
-                log.error("异步保存购物车到数据库失败, tableId={}, error={}", cart.getTableId(), e.getMessage(), e);
-            }
-        }, CART_DB_WRITE_EXECUTOR);
-    }
-
-    /**
-     * 保存购物车到Redis
-     */
-    private void saveCartToRedis(CartDTO cart) {
-        String cartKey = CART_KEY_PREFIX + cart.getTableId();
-        String cartJson = JSON.toJSONString(cart);
-        baseRedisService.setString(cartKey, cartJson, (long) CART_EXPIRE_SECONDS);
-    }
-
-    /**
-     * 保存购物车到数据库(优化后的批量操作版本)
-     * 使用批量逻辑删除和批量插入,提高性能
-     */
-    private void saveCartToDatabase(CartDTO cart) {
-        try {
-            Date now = new Date();
-            Integer userId = TokenUtil.getCurrentUserId();
-
-            // 1. 批量逻辑删除该桌号的所有购物车记录(使用 MyBatis-Plus 的 deleteBatchIds)
-            LambdaQueryWrapper<StoreCart> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(StoreCart::getTableId, cart.getTableId())
-                    .eq(StoreCart::getDeleteFlag, 0);
-            List<StoreCart> existingCartList = storeCartMapper.selectList(queryWrapper);
-            if (existingCartList != null && !existingCartList.isEmpty()) {
-                List<Integer> cartIds = existingCartList.stream()
-                        .map(StoreCart::getId)
-                        .collect(Collectors.toList());
-                // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-                storeCartMapper.deleteBatchIds(cartIds);
-            }
-
-            // 2. 批量插入新的购物车记录
-            if (cart.getItems() != null && !cart.getItems().isEmpty()) {
-                List<StoreCart> cartList = new ArrayList<>(cart.getItems().size());
-                for (CartItemDTO item : cart.getItems()) {
-                    StoreCart storeCart = new StoreCart();
-                    storeCart.setTableId(cart.getTableId());
-                    storeCart.setStoreId(cart.getStoreId());
-                    storeCart.setCuisineId(item.getCuisineId());
-                    storeCart.setCuisineName(item.getCuisineName());
-                    storeCart.setCuisineImage(item.getCuisineImage());
-                    storeCart.setUnitPrice(item.getUnitPrice());
-                    storeCart.setQuantity(item.getQuantity());
-                    storeCart.setLockedQuantity(item.getLockedQuantity());
-                    storeCart.setSubtotalAmount(item.getSubtotalAmount());
-                    storeCart.setAddUserId(item.getAddUserId());
-                    storeCart.setAddUserPhone(item.getAddUserPhone());
-                    storeCart.setRemark(item.getRemark());
-                    storeCart.setDeleteFlag(0);
-                    storeCart.setCreatedTime(now);
-                    storeCart.setCreatedUserId(userId);
-                    storeCart.setUpdatedTime(now);
-                    cartList.add(storeCart);
-                }
-
-                // 批量插入(如果数量较少,直接循环插入;如果数量较多,可以考虑分批插入)
-                if (cartList.size() <= 50) {
-                    // 小批量直接插入
-                    for (StoreCart storeCart : cartList) {
-                        storeCartMapper.insert(storeCart);
-                    }
-                } else {
-                    // 大批量分批插入(每批50条)
-                    int batchSize = 50;
-                    for (int i = 0; i < cartList.size(); i += batchSize) {
-                        int end = Math.min(i + batchSize, cartList.size());
-                        List<StoreCart> batch = cartList.subList(i, end);
-                        for (StoreCart storeCart : batch) {
-                            storeCartMapper.insert(storeCart);
-                        }
-                    }
-                }
-            }
-
-            // 3. 更新桌号表的购物车统计
-            StoreTable table = storeTableMapper.selectById(cart.getTableId());
-            if (table != null) {
-                table.setCartItemCount(cart.getTotalQuantity());
-                table.setCartTotalAmount(cart.getTotalAmount());
-                storeTableMapper.updateById(table);
-            }
-
-            log.debug("购物车数据已异步保存到数据库, tableId={}, itemCount={}", 
-                    cart.getTableId(), cart.getItems() != null ? cart.getItems().size() : 0);
-        } catch (Exception e) {
-            log.error("保存购物车到数据库失败, tableId={}, error={}", cart.getTableId(), e.getMessage(), e);
-            // 数据库保存失败不影响Redis,继续执行
-        }
-    }
-}

+ 0 - 39
alien-store/src/main/java/shop/alien/store/service/impl/DiningCollectServiceImpl.java

@@ -1,39 +0,0 @@
-package shop.alien.store.service.impl;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import shop.alien.store.feign.AlienStoreFeign;
-import shop.alien.store.service.DiningCollectService;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeCollect;
-
-/**
- * 点餐模块-收藏服务实现(透传 Feign 调 store)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/01/XX
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class DiningCollectServiceImpl implements DiningCollectService {
-
-    private final AlienStoreFeign alienStoreFeign;
-
-    @Override
-    public R<Boolean> addCollect(LifeCollect lifeCollect) {
-        log.info("DiningCollectService.addCollect lifeCollect={}", lifeCollect);
-        try {
-            R<Boolean> result = alienStoreFeign.addCollect(lifeCollect);
-            if (result == null) {
-                return R.fail("添加收藏失败");
-            }
-            return result;
-        } catch (Exception e) {
-            log.error("DiningCollectService.addCollect ERROR Msg={}", e.getMessage());
-            return R.fail("添加收藏失败");
-        }
-    }
-}

+ 0 - 471
alien-store/src/main/java/shop/alien/store/service/impl/DiningCouponServiceImpl.java

@@ -1,471 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-import shop.alien.store.feign.AlienStoreFeign;
-import shop.alien.store.service.DiningCouponService;
-import shop.alien.store.util.TokenUtil;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeDiscountCoupon;
-import shop.alien.entity.store.LifeDiscountCouponUser;
-import shop.alien.entity.store.vo.LifeDiscountCouponVo;
-import shop.alien.mapper.LifeDiscountCouponMapper;
-import shop.alien.mapper.LifeDiscountCouponUserMapper;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * 点餐模块-优惠券服务实现(透传 Feign 调 store,满足小程序我的优惠券/详情/选券)
- *
- * @author ssk
- * @version 1.0
- * @date 2025/1/29
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class DiningCouponServiceImpl implements DiningCouponService {
-
-    private final AlienStoreFeign alienStoreFeign;
-    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
-    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
-
-    @Override
-    public R<List<LifeDiscountCouponVo>> getUserCouponList(String authorization, int page, int size, String tabType, Integer type, Integer couponType, String storeId, String storeName) {
-        log.info("DiningCouponService.getUserCouponList page={}, size={}, tabType={}, type={}, couponType={}, storeId={}, storeName={}", page, size, tabType, type, couponType, storeId, storeName);
-        try {
-            // 参数校验
-            if (StringUtils.isEmpty(tabType)) {
-                log.warn("tabType参数为空");
-                return R.fail("分页类型不能为空");
-            }
-            if (page < 1) {
-                page = 1;
-            }
-            if (size < 1 || size > 100) {
-                size = 10;
-            }
-            
-            R<List<LifeDiscountCouponVo>> result = alienStoreFeign.getUserCouponList(authorization, tabType, page, size, type, couponType, storeId, storeName);
-            if (result == null) {
-                log.error("Feign调用返回null");
-                return R.fail("获取优惠券列表失败:服务返回为空");
-            }
-            // 如果 Feign 返回的是失败结果,直接返回
-            if (!result.isSuccess()) {
-                log.warn("Feign调用返回失败: code={}, msg={}", result.getCode(), result.getMsg());
-                return result;
-            }
-            return result;
-        } catch (Exception e) {
-            log.error("DiningCouponService.getUserCouponList ERROR: {}", e.getMessage(), e);
-            return R.fail("获取优惠券列表失败: " + e.getMessage());
-        }
-    }
-
-    @Override
-    public R<LifeDiscountCouponVo> getCounponDetailById(String authorization, String counponId) {
-        log.info("DiningCouponService.getCounponDetailById counponId={}", counponId);
-        try {
-            R<LifeDiscountCouponVo> result = alienStoreFeign.getCounponDetailById(authorization, counponId);
-            if (result == null) {
-                return R.fail("获取优惠券详情失败");
-            }
-            return result;
-        } catch (Exception e) {
-            log.error("DiningCouponService.getCounponDetailById ERROR Msg={}", e.getMessage());
-            return R.fail("获取优惠券详情失败");
-        }
-    }
-
-    @Override
-    public R<Map<String, Object>> getStoreUserUsableCouponList(String authorization, String storeId, BigDecimal amount, Integer couponType) {
-        log.info("DiningCouponService.getStoreUserUsableCouponList storeId={}, amount={}, couponType={}", storeId, amount, couponType);
-        try {
-            R<Map<String, Object>> result = alienStoreFeign.getStoreUserUsableCouponList(authorization, storeId, amount, couponType);
-            if (result == null) {
-                return R.fail("获取门店可用优惠券列表失败");
-            }
-            return result;
-        } catch (Exception e) {
-            log.error("DiningCouponService.getStoreUserUsableCouponList ERROR Msg={}", e.getMessage());
-            return R.fail("获取门店可用优惠券列表失败");
-        }
-    }
-
-    @Override
-    public R<List<LifeDiscountCouponVo>> getUserOwnedCoupons(String storeId, BigDecimal amount) {
-        log.info("查询用户拥有的优惠券, storeId={}, amount={}", storeId, amount);
-
-        try {
-            // 获取当前用户ID
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-
-            // 查询用户拥有的优惠券(未使用且未过期的)
-            LambdaQueryWrapper<LifeDiscountCouponUser> userWrapper = new LambdaQueryWrapper<>();
-            userWrapper.eq(LifeDiscountCouponUser::getUserId, userId);
-            userWrapper.eq(LifeDiscountCouponUser::getStatus, 0); // 0:待使用
-            userWrapper.eq(LifeDiscountCouponUser::getDeleteFlag, 0);
-            userWrapper.ge(LifeDiscountCouponUser::getExpirationTime, LocalDate.now()); // 未过期
-            List<LifeDiscountCouponUser> userCoupons = lifeDiscountCouponUserMapper.selectList(userWrapper);
-
-            if (userCoupons == null || userCoupons.isEmpty()) {
-                log.info("用户没有可用的优惠券, userId={}", userId);
-                return R.data(new ArrayList<>());
-            }
-
-            // 获取优惠券ID列表
-            List<Integer> couponIds = userCoupons.stream()
-                    .map(LifeDiscountCouponUser::getCouponId)
-                    .collect(Collectors.toList());
-
-            // 查询优惠券详情
-            LambdaQueryWrapper<LifeDiscountCoupon> couponWrapper = new LambdaQueryWrapper<>();
-            couponWrapper.in(LifeDiscountCoupon::getId, couponIds);
-            couponWrapper.eq(LifeDiscountCoupon::getDeleteFlag, 0);
-            if (StringUtils.hasText(storeId)) {
-                couponWrapper.eq(LifeDiscountCoupon::getStoreId, storeId);
-            }
-            List<LifeDiscountCoupon> coupons = lifeDiscountCouponMapper.selectList(couponWrapper);
-
-            if (coupons == null || coupons.isEmpty()) {
-                log.info("未找到优惠券详情, userId={}, couponIds={}", userId, couponIds);
-                return R.data(new ArrayList<>());
-            }
-
-            // 转换为VO并设置用户券ID,同时过滤掉已过期和未在使用时间内的优惠券
-            LocalDate now = LocalDate.now();
-            List<LifeDiscountCouponVo> couponVos = new ArrayList<>();
-            for (LifeDiscountCoupon coupon : coupons) {
-                // 找到对应的用户券
-                LifeDiscountCouponUser userCoupon = userCoupons.stream()
-                        .filter(uc -> uc.getCouponId().equals(coupon.getId()))
-                        .findFirst()
-                        .orElse(null);
-
-                if (userCoupon == null) {
-                    continue;
-                }
-
-                // 过滤1:检查用户券的过期时间(expirationTime)
-                if (userCoupon.getExpirationTime() != null && now.isAfter(userCoupon.getExpirationTime())) {
-                    log.debug("过滤已过期的用户券, couponId={}, expirationTime={}, now={}", 
-                            coupon.getId(), userCoupon.getExpirationTime(), now);
-                    continue;
-                }
-
-                // 过滤2:检查优惠券的使用时间范围(startDate 和 endDate)
-                // 如果优惠券有设置使用时间范围,则检查当前日期是否在范围内
-                if (coupon.getStartDate() != null || coupon.getEndDate() != null) {
-                    boolean inTimeRange = true;
-                    if (coupon.getStartDate() != null && now.isBefore(coupon.getStartDate())) {
-                        // 当前日期早于开始日期,未在使用时间内
-                        inTimeRange = false;
-                    }
-                    if (coupon.getEndDate() != null && now.isAfter(coupon.getEndDate())) {
-                        // 当前日期晚于结束日期,未在使用时间内
-                        inTimeRange = false;
-                    }
-                    if (!inTimeRange) {
-                        log.debug("过滤未在使用时间内的优惠券, couponId={}, startDate={}, endDate={}, now={}", 
-                                coupon.getId(), coupon.getStartDate(), coupon.getEndDate(), now);
-                        continue;
-                    }
-                }
-
-                // 过滤3:检查优惠券的有效期(validDate)
-                if (coupon.getValidDate() != null && now.isAfter(coupon.getValidDate())) {
-                    log.debug("过滤已过期的优惠券(validDate), couponId={}, validDate={}, now={}", 
-                            coupon.getId(), coupon.getValidDate(), now);
-                    continue;
-                }
-
-                LifeDiscountCouponVo vo = convertToVo(coupon, userCoupon);
-                couponVos.add(vo);
-            }
-
-            // 排序:符合支付条件的优先,其次优惠力度大的优先
-            if (amount != null) {
-                couponVos.sort((vo1, vo2) -> {
-                    // 判断是否符合支付条件(满足最低消费要求)
-                    boolean vo1CanUse = vo1.getMinimumSpendingAmount() == null
-                            || vo1.getMinimumSpendingAmount().compareTo(amount) <= 0;
-                    boolean vo2CanUse = vo2.getMinimumSpendingAmount() == null
-                            || vo2.getMinimumSpendingAmount().compareTo(amount) <= 0;
-
-                    // 第一优先级:符合支付条件的优先
-                    if (vo1CanUse && !vo2CanUse) {
-                        return -1; // vo1 排在前面
-                    }
-                    if (!vo1CanUse && vo2CanUse) {
-                        return 1; // vo2 排在前面
-                    }
-
-                    // 第二优先级:优惠力度大的优先(根据优惠券类型计算实际优惠金额)
-                    BigDecimal discountAmount1 = calculateDiscountAmountForVO(vo1, amount);
-                    BigDecimal discountAmount2 = calculateDiscountAmountForVO(vo2, amount);
-                    return discountAmount2.compareTo(discountAmount1); // 降序排列
-                });
-            } else {
-                // 如果没有提供金额,无法计算折扣券的实际优惠金额,只按面值排序(满减券)
-                // 注意:这种情况下折扣券无法准确排序,建议前端传入订单金额
-                couponVos.sort((vo1, vo2) -> {
-                    BigDecimal nominalValue1 = vo1.getNominalValue() != null ? vo1.getNominalValue() : BigDecimal.ZERO;
-                    BigDecimal nominalValue2 = vo2.getNominalValue() != null ? vo2.getNominalValue() : BigDecimal.ZERO;
-                    return nominalValue2.compareTo(nominalValue1); // 降序排列
-                });
-            }
-
-            log.info("查询用户拥有的优惠券成功, userId={}, count={}", userId, couponVos.size());
-            return R.data(couponVos);
-
-        } catch (Exception e) {
-            log.error("查询用户拥有的优惠券失败: {}", e.getMessage(), e);
-            return R.fail("查询用户拥有的优惠券失败: " + e.getMessage());
-        }
-    }
-
-    @Override
-    public R<List<LifeDiscountCouponVo>> getStoreUserCouponList(String authorization, String storeId, Integer couponType) {
-        log.info("DiningCouponService.getStoreUserCouponList storeId={}, couponType={}", storeId, couponType);
-        try {
-            R<List<LifeDiscountCouponVo>> result = alienStoreFeign.getStoreUserCouponList(authorization, storeId, couponType);
-            if (result == null) {
-                return R.fail("获取该用户该店铺优惠券列表失败");
-            }
-            return result;
-        } catch (Exception e) {
-            log.error("DiningCouponService.getStoreUserCouponList ERROR Msg={}", e.getMessage());
-            return R.fail("获取该用户该店铺优惠券列表失败");
-        }
-    }
-
-    @Override
-    public R<IPage<LifeDiscountCouponVo>> getStoreAllCouponList(String authorization, int page, int size, String storeId,
-                                                                String couponName, String tab, int couponsFromType,
-                                                                int couponStatus, Integer couponType) {
-        log.info("DiningCouponService.getStoreAllCouponList storeId={}, page={}, size={}, couponName={}, tab={}, couponsFromType={}, couponStatus={}, couponType={}",
-                storeId, page, size, couponName, tab, couponsFromType, couponStatus, couponType);
-        try {
-            // Feign 返回 Page 类型(具体实现类),但 Service 接口使用 IPage(接口类型)
-            // Page 实现了 IPage,所以可以直接返回
-            R<com.baomidou.mybatisplus.extension.plugins.pagination.Page<LifeDiscountCouponVo>> result = alienStoreFeign.getStoreAllCouponList(
-                    authorization, page, size, storeId, couponName, tab, couponsFromType, couponStatus, couponType);
-            if (result == null) {
-                return R.fail("获取该店铺所有优惠券列表失败");
-            }
-            // Page 实现了 IPage 接口,可以直接转换
-            return R.data(result.getData());
-        } catch (Exception e) {
-            log.error("DiningCouponService.getStoreAllCouponList ERROR Msg={}", e.getMessage(), e);
-            return R.fail("获取该店铺所有优惠券列表失败");
-        }
-    }
-
-    @Override
-    public R<List<LifeDiscountCouponVo>> getUserOwnedCouponsByStore(String storeId, Integer couponType) {
-        log.info("查询用户目前所拥有的优惠券, storeId={}, couponType={}", storeId, couponType);
-
-        try {
-            // 获取当前用户ID
-            Integer userId = TokenUtil.getCurrentUserId();
-            if (userId == null) {
-                return R.fail("用户未登录");
-            }
-
-            // 查询用户拥有的优惠券(未使用且未过期的)
-            LambdaQueryWrapper<LifeDiscountCouponUser> userWrapper = new LambdaQueryWrapper<>();
-            userWrapper.eq(LifeDiscountCouponUser::getUserId, userId);
-            userWrapper.eq(LifeDiscountCouponUser::getStatus, 0); // 0:待使用
-            userWrapper.eq(LifeDiscountCouponUser::getDeleteFlag, 0);
-            userWrapper.ge(LifeDiscountCouponUser::getExpirationTime, LocalDate.now()); // 未过期
-            List<LifeDiscountCouponUser> userCoupons = lifeDiscountCouponUserMapper.selectList(userWrapper);
-
-            if (userCoupons == null || userCoupons.isEmpty()) {
-                log.info("用户没有可用的优惠券, userId={}", userId);
-                return R.data(new ArrayList<>());
-            }
-
-            // 获取优惠券ID列表
-            List<Integer> couponIds = userCoupons.stream()
-                    .map(LifeDiscountCouponUser::getCouponId)
-                    .collect(Collectors.toList());
-
-            // 查询优惠券详情
-            LambdaQueryWrapper<LifeDiscountCoupon> couponWrapper = new LambdaQueryWrapper<>();
-            couponWrapper.in(LifeDiscountCoupon::getId, couponIds);
-            couponWrapper.eq(LifeDiscountCoupon::getDeleteFlag, 0);
-            // 如果提供了商铺ID,则只查询该商铺的优惠券
-            if (StringUtils.hasText(storeId)) {
-                couponWrapper.eq(LifeDiscountCoupon::getStoreId, storeId);
-            }
-            // 如果提供了优惠券类型,则只查询该类型的优惠券
-            if (couponType != null) {
-                couponWrapper.eq(LifeDiscountCoupon::getCouponType, couponType);
-            }
-            List<LifeDiscountCoupon> coupons = lifeDiscountCouponMapper.selectList(couponWrapper);
-
-            if (coupons == null || coupons.isEmpty()) {
-                log.info("未找到优惠券详情, userId={}, storeId={}, couponIds={}", userId, storeId, couponIds);
-                return R.data(new ArrayList<>());
-            }
-
-            // 转换为VO并设置用户券ID,同时过滤掉已过期和未在使用时间内的优惠券
-            LocalDate now = LocalDate.now();
-            List<LifeDiscountCouponVo> couponVos = new ArrayList<>();
-            for (LifeDiscountCoupon coupon : coupons) {
-                // 找到对应的用户券
-                LifeDiscountCouponUser userCoupon = userCoupons.stream()
-                        .filter(uc -> uc.getCouponId().equals(coupon.getId()))
-                        .findFirst()
-                        .orElse(null);
-
-                if (userCoupon == null) {
-                    continue;
-                }
-
-                // 过滤1:检查用户券的过期时间(expirationTime)
-                if (userCoupon.getExpirationTime() != null && now.isAfter(userCoupon.getExpirationTime())) {
-                    log.debug("过滤已过期的用户券, couponId={}, expirationTime={}, now={}", 
-                            coupon.getId(), userCoupon.getExpirationTime(), now);
-                    continue;
-                }
-
-                // 过滤2:检查优惠券的使用时间范围(startDate 和 endDate)
-                // 如果优惠券有设置使用时间范围,则检查当前日期是否在范围内
-                if (coupon.getStartDate() != null || coupon.getEndDate() != null) {
-                    boolean inTimeRange = true;
-                    if (coupon.getStartDate() != null && now.isBefore(coupon.getStartDate())) {
-                        // 当前日期早于开始日期,未在使用时间内
-                        inTimeRange = false;
-                    }
-                    if (coupon.getEndDate() != null && now.isAfter(coupon.getEndDate())) {
-                        // 当前日期晚于结束日期,未在使用时间内
-                        inTimeRange = false;
-                    }
-                    if (!inTimeRange) {
-                        log.debug("过滤未在使用时间内的优惠券, couponId={}, startDate={}, endDate={}, now={}", 
-                                coupon.getId(), coupon.getStartDate(), coupon.getEndDate(), now);
-                        continue;
-                    }
-                }
-
-                // 过滤3:检查优惠券的有效期(validDate)
-                if (coupon.getValidDate() != null && now.isAfter(coupon.getValidDate())) {
-                    log.debug("过滤已过期的优惠券(validDate), couponId={}, validDate={}, now={}", 
-                            coupon.getId(), coupon.getValidDate(), now);
-                    continue;
-                }
-
-                LifeDiscountCouponVo vo = convertToVo(coupon, userCoupon);
-                couponVos.add(vo);
-            }
-
-            // 按创建时间倒序排列(最新的在前)
-            couponVos.sort((vo1, vo2) -> {
-                if (vo1.getCreatedTime() == null && vo2.getCreatedTime() == null) {
-                    return 0;
-                }
-                if (vo1.getCreatedTime() == null) {
-                    return 1;
-                }
-                if (vo2.getCreatedTime() == null) {
-                    return -1;
-                }
-                return vo2.getCreatedTime().compareTo(vo1.getCreatedTime()); // 降序排列
-            });
-
-            log.info("查询用户拥有的优惠券成功, userId={}, storeId={}, count={}", userId, storeId, couponVos.size());
-            return R.data(couponVos);
-
-        } catch (Exception e) {
-            log.error("查询用户拥有的优惠券失败: {}", e.getMessage(), e);
-            return R.fail("查询用户拥有的优惠券失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * 将优惠券实体转换为VO
-     */
-    private LifeDiscountCouponVo convertToVo(LifeDiscountCoupon coupon, LifeDiscountCouponUser userCoupon) {
-        LifeDiscountCouponVo vo = new LifeDiscountCouponVo();
-        vo.setId(coupon.getId());
-        vo.setUserCouponId(userCoupon.getId());
-        vo.setStoreId(coupon.getStoreId());
-        vo.setUserId(String.valueOf(userCoupon.getUserId()));
-        vo.setCouponId(coupon.getId());
-        vo.setName(coupon.getName());
-        vo.setNominalValue(coupon.getNominalValue());
-        vo.setExpirationDate(coupon.getExpirationDate());
-        vo.setStartDate(coupon.getStartDate());
-        vo.setEndDate(coupon.getEndDate());
-        vo.setSingleQty(coupon.getSingleQty());
-        vo.setSupplementaryInstruction(coupon.getSupplementaryInstruction());
-        vo.setGetStatus(coupon.getGetStatus());
-        vo.setRestrictedQuantity(coupon.getRestrictedQuantity());
-        vo.setMinimumSpendingAmount(coupon.getMinimumSpendingAmount());
-        vo.setType(coupon.getType());
-        vo.setAttentionCanReceived(coupon.getAttentionCanReceived());
-        vo.setExpirationTime(userCoupon.getExpirationTime());
-        vo.setCreatedTime(coupon.getCreatedTime());
-        vo.setCouponType(coupon.getCouponType());
-        vo.setDiscountRate(coupon.getDiscountRate());
-        return vo;
-    }
-
-    /**
-     * 计算优惠券的实际优惠金额(用于排序)
-     * 根据优惠券类型(满减券或折扣券)计算实际优惠金额
-     *
-     * @param vo          优惠券VO
-     * @param orderAmount 订单金额(用于计算折扣券的优惠金额)
-     * @return 实际优惠金额
-     */
-    private BigDecimal calculateDiscountAmountForVO(LifeDiscountCouponVo vo, BigDecimal orderAmount) {
-        if (vo == null) {
-            return BigDecimal.ZERO;
-        }
-
-        Integer couponType = vo.getCouponType();
-        BigDecimal discountAmount = BigDecimal.ZERO;
-
-        if (couponType != null && couponType == 2) {
-            // 折扣券:根据折扣率计算优惠金额
-            // discountRate: 0-100,例如80表示8折,优惠金额 = 订单金额 * (100 - discountRate) / 100
-            BigDecimal discountRate = vo.getDiscountRate();
-            if (discountRate != null && discountRate.compareTo(BigDecimal.ZERO) > 0 
-                    && discountRate.compareTo(new BigDecimal(100)) <= 0 && orderAmount != null 
-                    && orderAmount.compareTo(BigDecimal.ZERO) > 0) {
-                // 计算折扣后的金额
-                BigDecimal discountedAmount = orderAmount.multiply(discountRate)
-                        .divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
-                // 优惠金额 = 原价 - 折扣后价格
-                discountAmount = orderAmount.subtract(discountedAmount);
-            }
-        } else {
-            // 满减券(默认或couponType=1):使用nominalValue
-            discountAmount = vo.getNominalValue();
-            if (discountAmount == null) {
-                discountAmount = BigDecimal.ZERO;
-            }
-            // 优惠金额不能超过订单总金额
-            if (orderAmount != null && discountAmount.compareTo(orderAmount) > 0) {
-                discountAmount = orderAmount;
-            }
-        }
-
-        return discountAmount;
-    }
-}

+ 0 - 690
alien-store/src/main/java/shop/alien/store/service/impl/DiningServiceImpl.java

@@ -1,690 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-import shop.alien.entity.store.*;
-import shop.alien.entity.store.dto.CartDTO;
-import shop.alien.entity.store.dto.CartItemDTO;
-import shop.alien.entity.store.vo.*;
-import shop.alien.mapper.*;
-import shop.alien.store.config.BaseRedisService;
-import shop.alien.store.service.CartService;
-import shop.alien.store.service.DiningService;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 点餐服务实现类
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class DiningServiceImpl implements DiningService {
-
-    private final StoreTableMapper storeTableMapper;
-    private final StoreInfoMapper storeInfoMapper;
-    private final StoreCuisineMapper storeCuisineMapper;
-    private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
-    private final StoreCuisineComboMapper storeCuisineComboMapper;
-    private final StoreOrderDetailMapper storeOrderDetailMapper;
-    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
-    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
-    private final CartService cartService;
-    private final BaseRedisService baseRedisService;
-    private final shop.alien.store.service.StoreOrderService storeOrderService;
-    private final StoreOrderMapper storeOrderMapper;
-    private final shop.alien.store.service.OrderLockService orderLockService;
-
-    @Override
-    public TableDiningStatusVO getTableDiningStatus(Integer tableId) {
-        if (tableId == null) {
-            return new TableDiningStatusVO(null, false, null);
-        }
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table == null) {
-            return new TableDiningStatusVO(tableId, false, null);
-        }
-        // 就餐中(1)、加餐(3) 均视为就餐状态;且需已有就餐人数
-        Integer status = table.getStatus();
-        boolean inDining = (Integer.valueOf(1).equals(status) || Integer.valueOf(3).equals(status))
-                && table.getDinerCount() != null && table.getDinerCount() > 0;
-        Integer dinerCount = inDining ? table.getDinerCount() : null;
-        return new TableDiningStatusVO(tableId, inDining, dinerCount);
-    }
-
-    @Override
-    public DiningPageInfoVO getDiningPageInfo(Integer tableId, Integer dinerCount) {
-        log.info("获取点餐页面信息, tableId={}, dinerCount={}", tableId, dinerCount);
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table == null) {
-            throw new RuntimeException("桌号不存在");
-        }
-
-        StoreInfo storeInfo = storeInfoMapper.selectById(table.getStoreId());
-        if (storeInfo == null) {
-            throw new RuntimeException("门店不存在");
-        }
-
-        // 第一个用户:传入用餐人数时,将餐桌置为就餐中并保存就餐人数
-        if (dinerCount != null && dinerCount > 0) {
-            table.setStatus(1); // 就餐中
-            table.setDinerCount(dinerCount);
-            storeTableMapper.updateById(table);
-            log.info("首客选桌并填写用餐人数, tableId={}, dinerCount={}, 餐桌状态已置为就餐中", tableId, dinerCount);
-        } else {
-            // 第二个及后续用户:若餐桌已就餐中且表内已有就餐人数,直接使用
-            if (Integer.valueOf(1).equals(table.getStatus()) && table.getDinerCount() != null && table.getDinerCount() > 0) {
-                dinerCount = table.getDinerCount();
-                log.info("餐桌已就餐中,使用已保存的就餐人数, tableId={}, dinerCount={}", tableId, dinerCount);
-            } else {
-                // 餐桌空闲且未传就餐人数时要求必填
-                throw new RuntimeException("请选择用餐人数");
-            }
-        }
-
-        DiningPageInfoVO vo = new DiningPageInfoVO();
-        vo.setStoreName(storeInfo.getStoreName());
-        vo.setTableNumber(table.getTableNumber());
-        vo.setDinerCount(dinerCount);
-        vo.setStoreId(table.getStoreId());
-        vo.setTableId(tableId);
-
-        return vo;
-    }
-
-    @Override
-    public List<CuisineListVO> searchCuisines(Integer storeId, String keyword, Integer tableId) {
-        log.info("搜索菜品, storeId={}, keyword={}, tableId={}", storeId, keyword, tableId);
-
-        // 限制搜索关键词长度
-        if (StringUtils.hasText(keyword) && keyword.length() > 10) {
-            keyword = keyword.substring(0, 10);
-        }
-
-        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisine::getStoreId, storeId);
-        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的
-        if (StringUtils.hasText(keyword)) {
-            wrapper.like(StoreCuisine::getName, keyword);
-        }
-        wrapper.orderByDesc(StoreCuisine::getCreatedTime);
-
-        List<StoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
-        return convertToCuisineListVO(cuisines, tableId);
-    }
-
-    @Override
-    public List<CuisineListVO> getCuisinesByCategory(Integer storeId, Integer categoryId, Integer tableId, Integer page, Integer size) {
-        log.info("根据分类获取菜品列表, storeId={}, categoryId={}, tableId={}, page={}, size={}", storeId, categoryId, tableId, page, size);
-
-        if (page == null || page < 1) {
-            page = 1;
-        }
-        if (size == null || size < 1) {
-            size = 12;
-        }
-
-        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisine::getStoreId, storeId);
-        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的
-        if (categoryId != null) {
-            // 这里假设菜品表有category_id字段,如果没有需要关联查询
-            // wrapper.eq(StoreCuisine::getCategoryId, categoryId);
-        }
-        wrapper.orderByDesc(StoreCuisine::getCreatedTime);
-
-        // 分页查询
-        int offset = (page - 1) * size;
-        wrapper.last("LIMIT " + offset + ", " + size);
-
-        List<StoreCuisine> cuisines = storeCuisineMapper.selectList(wrapper);
-        return convertToCuisineListVO(cuisines, tableId);
-    }
-
-    @Override
-    public CuisineDetailVO getCuisineDetail(Integer cuisineId, Integer tableId) {
-        log.info("获取菜品详情, cuisineId={}, tableId={}", cuisineId, tableId);
-
-        StoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
-        if (cuisine == null) {
-            throw new RuntimeException("菜品不存在");
-        }
-
-        CuisineDetailVO vo = new CuisineDetailVO();
-        // 手动映射所有字段,确保所有属性都被正确复制
-        vo.setId(cuisine.getId());
-        vo.setStoreId(cuisine.getStoreId());
-        vo.setName(cuisine.getName());
-        vo.setTotalPrice(cuisine.getTotalPrice());
-        vo.setCuisineType(cuisine.getCuisineType());
-        vo.setCategoryIds(cuisine.getCategoryIds());
-        vo.setTags(cuisine.getTags());
-        vo.setDishReview(cuisine.getDishReview());
-        vo.setDescription(cuisine.getDescription());
-        vo.setDetailContent(cuisine.getDetailContent());
-        vo.setImageContent(cuisine.getImageContent());
-        vo.setExtraNote(cuisine.getExtraNote());
-        vo.setNeedReserve(cuisine.getNeedReserve());
-        vo.setReserveRule(cuisine.getReserveRule());
-        vo.setPeopleLimit(cuisine.getPeopleLimit());
-        vo.setUsageRule(cuisine.getUsageRule());
-
-        // 处理图片列表
-        if (StringUtils.hasText(cuisine.getImages())) {
-            List<String> images = Arrays.asList(cuisine.getImages().split(","));
-            vo.setImages(images);
-        } else {
-            vo.setImages(new ArrayList<>());
-        }
-
-        // 计算月售数量
-        vo.setMonthlySales(getMonthlySales(cuisineId));
-
-        // 获取购物车数量
-        CartDTO cart = cartService.getCart(tableId);
-        if (cart.getItems() != null) {
-            Optional<CartItemDTO> cartItem = cart.getItems().stream()
-                    .filter(item -> item.getCuisineId().equals(cuisineId))
-                    .findFirst();
-            vo.setCartQuantity(cartItem.map(CartItemDTO::getQuantity).orElse(0));
-        } else {
-            vo.setCartQuantity(0);
-        }
-
-        // 如果是套餐,获取套餐包含的菜品
-        if (cuisine.getCuisineType() != null && cuisine.getCuisineType() == 2) {
-            LambdaQueryWrapper<StoreCuisineCombo> comboWrapper = new LambdaQueryWrapper<>();
-            comboWrapper.eq(StoreCuisineCombo::getCid, cuisineId);
-            comboWrapper.eq(StoreCuisineCombo::getDeleteFlag, 0);
-            List<StoreCuisineCombo> combos = storeCuisineComboMapper.selectList(comboWrapper);
-
-            List<CuisineComboItemVO> comboItems = combos.stream().map(combo -> {
-                CuisineComboItemVO item = new CuisineComboItemVO();
-                item.setCuisineId(combo.getSid());
-                item.setQuantity(combo.getSnum());
-                item.setCategory(combo.getCategory());
-                // 查询菜品名称
-                StoreCuisine comboCuisine = storeCuisineMapper.selectById(combo.getSid());
-                if (comboCuisine != null) {
-                    item.setCuisineName(comboCuisine.getName());
-                }
-                return item;
-            }).collect(Collectors.toList());
-            vo.setComboItems(comboItems);
-        }
-
-        return vo;
-    }
-
-    @Override
-    public List<AvailableCouponVO> getAvailableCoupons(Integer storeId, Integer userId) {
-        log.info("获取可领取优惠券列表, storeId={}, userId={}", storeId, userId);
-
-        // 查询门店的优惠券
-        LambdaQueryWrapper<LifeDiscountCoupon> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(LifeDiscountCoupon::getStoreId, String.valueOf(storeId));
-        wrapper.eq(LifeDiscountCoupon::getDeleteFlag, 0);
-        wrapper.eq(LifeDiscountCoupon::getGetStatus, 1); // 开启领取
-        wrapper.gt(LifeDiscountCoupon::getSingleQty, 0); // 有库存
-        LocalDate now = LocalDate.now();
-        wrapper.le(LifeDiscountCoupon::getStartDate, now);
-        wrapper.ge(LifeDiscountCoupon::getEndDate, now);
-        wrapper.orderByDesc(LifeDiscountCoupon::getCreatedTime);
-
-        List<LifeDiscountCoupon> coupons = lifeDiscountCouponMapper.selectList(wrapper);
-
-        // 查询用户已领取的优惠券
-        Set<Integer> receivedCouponIds = new HashSet<>();
-        if (userId != null) {
-            LambdaQueryWrapper<LifeDiscountCouponUser> userWrapper = new LambdaQueryWrapper<>();
-            userWrapper.eq(LifeDiscountCouponUser::getUserId, userId);
-            List<LifeDiscountCouponUser> userCoupons = lifeDiscountCouponUserMapper.selectList(userWrapper);
-            receivedCouponIds = userCoupons.stream()
-                    .map(LifeDiscountCouponUser::getCouponId)
-                    .collect(Collectors.toSet());
-        }
-
-        final Set<Integer> finalReceivedCouponIds = receivedCouponIds;
-        return coupons.stream().map(coupon -> {
-            AvailableCouponVO vo = new AvailableCouponVO();
-            vo.setId(coupon.getId());
-            vo.setName(coupon.getName());
-            vo.setNominalValue(coupon.getNominalValue());
-            vo.setMinimumSpendingAmount(coupon.getMinimumSpendingAmount());
-            vo.setEndDate(coupon.getEndDate());
-            vo.setIsReceived(finalReceivedCouponIds.contains(coupon.getId()));
-            vo.setIsAvailable(coupon.getSingleQty() > 0 && coupon.getEndDate().isAfter(now) || coupon.getEndDate().isEqual(now));
-            // 设置优惠券类型和折扣率(如果需要,可以在VO中添加这些字段)
-            return vo;
-        }).collect(Collectors.toList());
-    }
-
-    @Override
-    public boolean receiveCoupon(Integer couponId, Integer userId) {
-        log.info("领取优惠券, couponId={}, userId={}", couponId, userId);
-
-        LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(couponId);
-        if (coupon == null) {
-            throw new RuntimeException("优惠券不存在");
-        }
-
-        // 检查是否已领取
-        LambdaQueryWrapper<LifeDiscountCouponUser> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(LifeDiscountCouponUser::getUserId, userId);
-        wrapper.eq(LifeDiscountCouponUser::getCouponId, couponId);
-        LifeDiscountCouponUser existing = lifeDiscountCouponUserMapper.selectOne(wrapper);
-        if (existing != null) {
-            throw new RuntimeException("您已领取过该优惠券");
-        }
-
-        // 检查库存
-        if (coupon.getSingleQty() == null || coupon.getSingleQty() <= 0) {
-            throw new RuntimeException("优惠券已领完");
-        }
-
-        // 创建用户优惠券记录
-        LifeDiscountCouponUser userCoupon = new LifeDiscountCouponUser();
-        userCoupon.setUserId(userId);
-        userCoupon.setCouponId(couponId);
-        userCoupon.setReceiveTime(new Date());
-        userCoupon.setStatus(0); // 待使用
-        // 注意:如果需要设置 issueSource,需要确保 LifeDiscountCouponUser 实体类已包含该字段
-        if (coupon.getSpecifiedDay() != null && !coupon.getSpecifiedDay().isEmpty()) {
-            try {
-                int days = Integer.parseInt(coupon.getSpecifiedDay());
-                LocalDate expirationDate = LocalDate.now().plusDays(days);
-                userCoupon.setExpirationTime(expirationDate);
-            } catch (NumberFormatException e) {
-                userCoupon.setExpirationTime(coupon.getEndDate());
-            }
-        } else {
-            userCoupon.setExpirationTime(coupon.getEndDate());
-        }
-        lifeDiscountCouponUserMapper.insert(userCoupon);
-
-        // 更新库存
-        coupon.setSingleQty(coupon.getSingleQty() - 1);
-        lifeDiscountCouponMapper.updateById(coupon);
-
-        return true;
-    }
-
-    @Override
-    public OrderConfirmVO getOrderConfirmInfo(Integer tableId, Integer dinerCount, Integer userId) {
-        log.info("获取订单确认页面信息, tableId={}, dinerCount={}, userId={}", tableId, dinerCount, userId);
-
-        // 获取点餐页面信息(就餐中且未传人数时,内部会使用桌台已保存的就餐人数)
-        DiningPageInfoVO pageInfo = getDiningPageInfo(tableId, dinerCount);
-        int effectiveDinerCount = pageInfo.getDinerCount() != null && pageInfo.getDinerCount() > 0
-                ? pageInfo.getDinerCount() : (dinerCount != null ? dinerCount : 0);
-
-        // 获取购物车
-        CartDTO cart = cartService.getCart(tableId);
-
-        // 为购物车项补全菜品标签(购物车从 DB 加载时可能无 tags)
-        List<CartItemDTO> items = cart.getItems();
-        if (items != null && !items.isEmpty()) {
-            Set<Integer> cuisineIds = items.stream()
-                    .map(CartItemDTO::getCuisineId)
-                    .filter(Objects::nonNull)
-                    .collect(Collectors.toSet());
-            if (!cuisineIds.isEmpty()) {
-                List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
-                Map<Integer, String> tagsMap = new HashMap<>();
-                if (cuisines != null) {
-                    for (StoreCuisine c : cuisines) {
-                        if (c.getTags() != null) {
-                            tagsMap.put(c.getId(), c.getTags());
-                        }
-                    }
-                }
-                for (CartItemDTO item : items) {
-                    if (item.getCuisineId() != null && item.getTags() == null) {
-                        item.setTags(tagsMap.get(item.getCuisineId()));
-                    }
-                }
-            }
-        }
-
-        // 检查订单锁定
-        Integer lockUserId = orderLockService.checkOrderLock(tableId);
-        boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
-
-        OrderConfirmVO vo = new OrderConfirmVO();
-        vo.setStoreName(pageInfo.getStoreName());
-        vo.setTableNumber(pageInfo.getTableNumber());
-        vo.setDinerCount(pageInfo.getDinerCount() != null ? pageInfo.getDinerCount() : dinerCount);
-        // 联系电话和备注由前端传入,这里不设置默认值
-        vo.setItems(items != null ? items : cart.getItems());
-        vo.setTotalAmount(cart.getTotalAmount());
-        vo.setIsLocked(isLocked);
-        vo.setLockUserId(lockUserId);
-
-        // 计算餐具费(默认1元/人)
-        BigDecimal tablewareUnitPrice = new BigDecimal("1.00");
-        BigDecimal tablewareFee = BigDecimal.ZERO;
-        if (effectiveDinerCount > 0) {
-            tablewareFee = tablewareUnitPrice.multiply(BigDecimal.valueOf(effectiveDinerCount));
-        }
-        vo.setTablewareFee(tablewareFee);
-        vo.setTablewareUnitPrice(tablewareUnitPrice);
-
-        // 自动匹配最优惠的优惠券
-        List<AvailableCouponVO> availableCoupons = new ArrayList<>();
-        if (userId != null && cart.getTotalAmount().compareTo(BigDecimal.ZERO) > 0) {
-            availableCoupons = getAvailableCoupons(pageInfo.getStoreId(), userId);
-            // 过滤出可用的优惠券(已领取且满足最低消费)
-            BigDecimal totalWithTableware = cart.getTotalAmount().add(tablewareFee);
-            // 需要查询优惠券详情来计算实际优惠金额(用于排序)
-            List<Integer> couponIds = availableCoupons.stream()
-                    .filter(c -> c.getIsReceived() && c.getIsAvailable())
-                    .filter(c -> totalWithTableware.compareTo(c.getMinimumSpendingAmount() != null ? c.getMinimumSpendingAmount() : BigDecimal.ZERO) >= 0)
-                    .map(AvailableCouponVO::getId)
-                    .collect(Collectors.toList());
-            
-            // 查询优惠券详情用于计算实际优惠金额
-            Map<Integer, LifeDiscountCoupon> couponMap = new HashMap<>();
-            if (!couponIds.isEmpty()) {
-                List<LifeDiscountCoupon> couponDetails = lifeDiscountCouponMapper.selectBatchIds(couponIds);
-                couponMap = couponDetails.stream().collect(Collectors.toMap(LifeDiscountCoupon::getId, c -> c));
-            }
-            
-            final BigDecimal finalTotal = totalWithTableware;
-            final Map<Integer, LifeDiscountCoupon> finalCouponMap = couponMap;
-            List<AvailableCouponVO> usableCoupons = availableCoupons.stream()
-                    .filter(c -> c.getIsReceived() && c.getIsAvailable())
-                    .filter(c -> totalWithTableware.compareTo(c.getMinimumSpendingAmount() != null ? c.getMinimumSpendingAmount() : BigDecimal.ZERO) >= 0)
-                    .sorted((a, b) -> {
-                        // 根据实际优惠金额排序(考虑折扣券)
-                        BigDecimal discountA = calculateDiscountAmountForVO(a, finalCouponMap, finalTotal);
-                        BigDecimal discountB = calculateDiscountAmountForVO(b, finalCouponMap, finalTotal);
-                        return discountB.compareTo(discountA); // 降序排列
-                    })
-                    .collect(Collectors.toList());
-
-            if (!usableCoupons.isEmpty()) {
-                AvailableCouponVO bestCoupon = usableCoupons.get(0);
-                vo.setCouponId(bestCoupon.getId());
-                vo.setCouponName(bestCoupon.getName());
-                // 根据优惠券类型计算优惠金额
-                // 需要查询优惠券详情来计算折扣券的优惠金额
-                LifeDiscountCoupon couponDetail = lifeDiscountCouponMapper.selectById(bestCoupon.getId());
-                BigDecimal discountAmount = calculateDiscountAmount(couponDetail, cart.getTotalAmount().add(tablewareFee));
-                BigDecimal totalAmount = cart.getTotalAmount().add(tablewareFee);
-                vo.setDiscountAmount(discountAmount);
-                vo.setPayAmount(totalAmount.subtract(discountAmount));
-            } else {
-                vo.setPayAmount(cart.getTotalAmount().add(tablewareFee));
-            }
-        } else {
-            vo.setPayAmount(cart.getTotalAmount().add(tablewareFee));
-        }
-        vo.setAvailableCoupons(availableCoupons);
-
-        return vo;
-    }
-
-    @Override
-    public boolean lockOrder(Integer tableId, Integer userId) {
-        return orderLockService.lockOrder(tableId, userId);
-    }
-
-    @Override
-    public void unlockOrder(Integer tableId, Integer userId) {
-        orderLockService.unlockOrder(tableId, userId);
-    }
-
-    @Override
-    public Integer checkOrderLock(Integer tableId) {
-        return orderLockService.checkOrderLock(tableId);
-    }
-
-    /**
-     * 转换为菜品列表VO
-     */
-    private List<CuisineListVO> convertToCuisineListVO(List<StoreCuisine> cuisines, Integer tableId) {
-        // 获取购物车
-        CartDTO cart = cartService.getCart(tableId);
-        Map<Integer, Integer> cartQuantityMap = new HashMap<>();
-        if (cart.getItems() != null) {
-            cartQuantityMap = cart.getItems().stream()
-                    .collect(Collectors.toMap(CartItemDTO::getCuisineId, CartItemDTO::getQuantity));
-        }
-
-        // 批量查询月售数量
-        Map<Integer, Integer> monthlySalesMap = new HashMap<>();
-        for (StoreCuisine cuisine : cuisines) {
-            monthlySalesMap.put(cuisine.getId(), getMonthlySales(cuisine.getId()));
-        }
-
-        final Map<Integer, Integer> finalCartQuantityMap = cartQuantityMap;
-        final Map<Integer, Integer> finalMonthlySalesMap = monthlySalesMap;
-
-        return cuisines.stream().map(cuisine -> {
-            CuisineListVO vo = new CuisineListVO();
-            BeanUtils.copyProperties(cuisine, vo);
-            vo.setPrice(cuisine.getTotalPrice());
-
-            // 处理首张图片
-            if (StringUtils.hasText(cuisine.getImages())) {
-                String[] images = cuisine.getImages().split(",");
-                vo.setFirstImage(images.length > 0 ? images[0] : null);
-            }
-
-            // 设置购物车数量
-            vo.setCartQuantity(finalCartQuantityMap.getOrDefault(cuisine.getId(), 0));
-
-            // 设置月售数量
-            vo.setMonthlySales(finalMonthlySalesMap.getOrDefault(cuisine.getId(), 0));
-
-            return vo;
-        }).collect(Collectors.toList());
-    }
-
-    /**
-     * 获取菜品月售数量(当月1日至当前日期)
-     */
-    private Integer getMonthlySales(Integer cuisineId) {
-        try {
-            // 计算当月1日
-            Calendar calendar = Calendar.getInstance();
-            calendar.set(Calendar.DAY_OF_MONTH, 1);
-            calendar.set(Calendar.HOUR_OF_DAY, 0);
-            calendar.set(Calendar.MINUTE, 0);
-            calendar.set(Calendar.SECOND, 0);
-            calendar.set(Calendar.MILLISECOND, 0);
-            Date monthStart = calendar.getTime();
-
-            // 查询订单明细中该菜品的销售数量
-            LambdaQueryWrapper<StoreOrderDetail> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(StoreOrderDetail::getCuisineId, cuisineId);
-            wrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-            wrapper.ge(StoreOrderDetail::getCreatedTime, monthStart);
-            // 只统计已支付的订单
-            wrapper.inSql(StoreOrderDetail::getOrderId,
-                    "SELECT id FROM store_order WHERE pay_status = 1 AND delete_flag = 0");
-
-            List<StoreOrderDetail> details = storeOrderDetailMapper.selectList(wrapper);
-            return details.stream().mapToInt(StoreOrderDetail::getQuantity).sum();
-        } catch (Exception e) {
-            log.error("获取月售数量失败, cuisineId={}", cuisineId, e);
-            return 0;
-        }
-    }
-
-    @Override
-    public shop.alien.entity.store.vo.OrderSettlementVO getOrderSettlementInfo(Integer orderId, Integer userId) {
-        log.info("获取订单结算确认页面信息, orderId={}, userId={}", orderId, userId);
-
-        // 查询订单
-        shop.alien.entity.store.StoreOrder order = storeOrderService.getOrderById(orderId);
-        if (order == null) {
-            throw new RuntimeException("订单不存在");
-        }
-
-        // 查询订单明细
-        LambdaQueryWrapper<shop.alien.entity.store.StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-        detailWrapper.eq(shop.alien.entity.store.StoreOrderDetail::getOrderId, orderId);
-        detailWrapper.eq(shop.alien.entity.store.StoreOrderDetail::getDeleteFlag, 0);
-        detailWrapper.orderByDesc(shop.alien.entity.store.StoreOrderDetail::getCreatedTime);
-        List<shop.alien.entity.store.StoreOrderDetail> details = storeOrderDetailMapper.selectList(detailWrapper);
-
-        // 批量查询菜品标签
-        Set<Integer> cuisineIds = details.stream()
-                .map(shop.alien.entity.store.StoreOrderDetail::getCuisineId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        Map<Integer, String> cuisineIdToTags = new HashMap<>();
-        if (!cuisineIds.isEmpty()) {
-            List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
-            if (cuisines != null) {
-                for (StoreCuisine c : cuisines) {
-                    if (c.getTags() != null) {
-                        cuisineIdToTags.put(c.getId(), c.getTags());
-                    }
-                }
-            }
-        }
-
-        // 转换为CartItemDTO(含菜品标签)
-        Map<Integer, String> finalTagsMap = cuisineIdToTags;
-        List<shop.alien.entity.store.dto.CartItemDTO> items = details.stream().map(detail -> {
-            shop.alien.entity.store.dto.CartItemDTO item = new shop.alien.entity.store.dto.CartItemDTO();
-            item.setCuisineId(detail.getCuisineId());
-            item.setCuisineName(detail.getCuisineName());
-            item.setCuisineType(detail.getCuisineType());
-            item.setCuisineImage(detail.getCuisineImage());
-            item.setUnitPrice(detail.getUnitPrice());
-            item.setQuantity(detail.getQuantity());
-            item.setSubtotalAmount(detail.getSubtotalAmount());
-            item.setAddUserId(detail.getAddUserId());
-            item.setAddUserPhone(detail.getAddUserPhone());
-            item.setRemark(detail.getRemark());
-            item.setTags(detail.getCuisineId() != null ? finalTagsMap.get(detail.getCuisineId()) : null);
-            return item;
-        }).collect(Collectors.toList());
-
-        // 查询门店信息
-        shop.alien.entity.store.StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
-
-        // 检查结算锁定
-        Integer lockUserId = orderLockService.checkSettlementLock(orderId);
-        boolean isLocked = lockUserId != null && !lockUserId.equals(userId);
-
-        shop.alien.entity.store.vo.OrderSettlementVO vo = new shop.alien.entity.store.vo.OrderSettlementVO();
-        vo.setOrderId(order.getId());
-        vo.setOrderNo(order.getOrderNo());
-        vo.setStoreName(storeInfo != null ? storeInfo.getStoreName() : null);
-        vo.setTableNumber(order.getTableNumber());
-        vo.setDinerCount(order.getDinerCount());
-        vo.setContactPhone(order.getContactPhone());
-        vo.setRemark(order.getRemark());
-        vo.setItems(items);
-        vo.setTotalAmount(order.getTotalAmount());
-        vo.setTablewareFee(order.getTablewareFee() != null ? order.getTablewareFee() : BigDecimal.ZERO);
-        vo.setCouponId(order.getCouponId());
-        vo.setDiscountAmount(order.getDiscountAmount() != null ? order.getDiscountAmount() : BigDecimal.ZERO);
-        vo.setPayAmount(order.getPayAmount());
-        vo.setIsLocked(isLocked);
-        vo.setLockUserId(lockUserId);
-
-        // 查询优惠券名称
-        if (order.getCouponId() != null) {
-            shop.alien.entity.store.LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(order.getCouponId());
-            if (coupon != null) {
-                vo.setCouponName(coupon.getName());
-            }
-        }
-
-        return vo;
-    }
-
-    @Override
-    public boolean lockSettlement(Integer orderId, Integer userId) {
-        return orderLockService.lockSettlement(orderId, userId);
-    }
-
-    @Override
-    public void unlockSettlement(Integer orderId, Integer userId) {
-        orderLockService.unlockSettlement(orderId, userId);
-    }
-
-    @Override
-    public Integer checkSettlementLock(Integer orderId) {
-        return orderLockService.checkSettlementLock(orderId);
-    }
-
-    /**
-     * 计算优惠金额:根据优惠券类型(满减券或折扣券)计算
-     *
-     * @param coupon           优惠券对象
-     * @param totalWithTableware 订单总金额(含餐具费)
-     * @return 优惠金额
-     */
-    private BigDecimal calculateDiscountAmount(LifeDiscountCoupon coupon, BigDecimal totalWithTableware) {
-        if (coupon == null || totalWithTableware == null || totalWithTableware.compareTo(BigDecimal.ZERO) <= 0) {
-            return BigDecimal.ZERO;
-        }
-
-        Integer couponType = coupon.getCouponType();
-        BigDecimal discountAmount = BigDecimal.ZERO;
-
-        if (couponType != null && couponType == 2) {
-            // 折扣券:根据折扣率计算优惠金额
-            // discountRate: 0-100,例如80表示8折,优惠金额 = 订单金额 * (100 - discountRate) / 100
-            BigDecimal discountRate = coupon.getDiscountRate();
-            if (discountRate != null && discountRate.compareTo(BigDecimal.ZERO) > 0 && discountRate.compareTo(new BigDecimal(100)) <= 0) {
-                // 计算折扣后的金额
-                BigDecimal discountedAmount = totalWithTableware.multiply(discountRate).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
-                // 优惠金额 = 原价 - 折扣后价格
-                discountAmount = totalWithTableware.subtract(discountedAmount);
-            }
-        } else {
-            // 满减券(默认或couponType=1):使用nominalValue
-            discountAmount = coupon.getNominalValue();
-            if (discountAmount == null) {
-                discountAmount = BigDecimal.ZERO;
-            }
-            // 优惠金额不能超过订单总金额
-            if (discountAmount.compareTo(totalWithTableware) > 0) {
-                discountAmount = totalWithTableware;
-            }
-        }
-
-        return discountAmount;
-    }
-
-    /**
-     * 为VO计算优惠金额(用于排序)
-     *
-     * @param vo          优惠券VO
-     * @param couponMap   优惠券详情Map
-     * @param totalAmount 订单总金额
-     * @return 优惠金额
-     */
-    private BigDecimal calculateDiscountAmountForVO(AvailableCouponVO vo, Map<Integer, LifeDiscountCoupon> couponMap, BigDecimal totalAmount) {
-        if (vo == null || totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
-            return BigDecimal.ZERO;
-        }
-
-        LifeDiscountCoupon coupon = couponMap.get(vo.getId());
-        if (coupon == null) {
-            // 如果没有详情,使用nominalValue作为默认值
-            return vo.getNominalValue() != null ? vo.getNominalValue() : BigDecimal.ZERO;
-        }
-
-        return calculateDiscountAmount(coupon, totalAmount);
-    }
-}

+ 0 - 697
alien-store/src/main/java/shop/alien/store/service/impl/DiningUserServiceImpl.java

@@ -1,697 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import shop.alien.store.config.BaseRedisService;
-import shop.alien.store.dto.ChangePhoneDto;
-import shop.alien.store.dto.UserProfileUpdateDto;
-import shop.alien.store.feign.AlienStoreFeign;
-import shop.alien.store.service.DiningUserService;
-import shop.alien.store.util.TokenUtil;
-import shop.alien.store.util.WeChatMiniProgramUtil;
-import shop.alien.store.util.WeChatMiniProgramUtil.WeChatSessionInfo;
-import shop.alien.entity.result.R;
-import shop.alien.store.vo.DiningUserVo;
-import shop.alien.store.vo.TokenVerifyVo;
-import shop.alien.entity.store.LifeUser;
-import shop.alien.mapper.LifeUserMapper;
-import shop.alien.util.common.JwtUtil;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.MalformedJwtException;
-import io.jsonwebtoken.SignatureException;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 点餐用户服务实现类
- * 标准流程:通过 wx.login() 获取 code,调用 jscode2session 获取 openid
- *
- * @author ssk
- * @version 2.0
- * @date 2024/12/4
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class DiningUserServiceImpl implements DiningUserService {
-
-    private final LifeUserMapper lifeUserMapper;
-    private final BaseRedisService baseRedisService;
-    private final WeChatMiniProgramUtil weChatMiniProgramUtil;
-    private final AlienStoreFeign alienStoreFeign;
-
-    @Value("${jwt.expiration-time}")
-    private String effectiveTime;
-
-    /**
-     * Redis key 常量(小程序专用,避免与 APP 端冲突)
-     */
-    private static final String REDIS_KEY_OPENID_PREFIX = "wechat:openid:";
-    private static final String REDIS_KEY_TOKEN_PREFIX = "miniprogram_user_token:";
-    private static final String REDIS_KEY_USER_PHONE_PREFIX = "miniprogram_user_";
-    private static final long OPENID_MAPPING_EXPIRE_SECONDS = 30 * 24 * 60 * 60L; // 30天
-    private static final long TOKEN_EXPIRE_SECONDS = 7 * 24 * 60 * 60L; // 7天
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public DiningUserVo wechatLogin(String code, String phoneCode, String macIp) {
-        // 1. 通过 code2session 获取 openid 和 session_key
-        String openid = getOpenidFromCode(code);
-        if (StringUtils.isBlank(openid)) {
-            return null;
-        }
-
-        // 2. 如果提供了 phoneCode,先解析手机号(用于返回给前端和更新用户)
-        String parsedPhone = null;
-        if (StringUtils.isNotBlank(phoneCode)) {
-            parsedPhone = weChatMiniProgramUtil.getPhoneNumberByCode(phoneCode);
-            if (StringUtils.isNotBlank(parsedPhone)) {
-                log.info("成功解析手机号: {}", maskString(parsedPhone, 7));
-            } else {
-                log.warn("解析手机号失败,phoneCode可能已过期或无效");
-            }
-        }
-        if (StringUtils.isBlank(parsedPhone)) {
-            log.info("微信登录未传手机号或解析失败: openid={}, phoneCode={}", maskString(openid, 8), StringUtils.isNotBlank(phoneCode) ? "已传" : "未传");
-        }
-
-        // 3. 查找或创建用户(传入解析后的手机号,避免重复解析)
-        LifeUser user = findOrCreateUser(openid, parsedPhone);
-        if (user == null) {
-            return null;
-        }
-
-        // 4. 检查用户状态(提前检查,避免不必要的操作)
-        if (!isUserValid(user)) {
-            return null;
-        }
-
-        // 5. 生成并存储 token(传入本次解析的手机号,确保有手机号时一定写入 miniprogram_user_{phone})
-        String token = generateAndStoreToken(openid, user, parsedPhone);
-
-        // 6. 构建返回对象,优先使用解析后的手机号返回给前端
-        return buildDiningUserVo(user, token, openid, parsedPhone);
-    }
-
-    /**
-     * 通过 code 获取 openid
-     */
-    private String getOpenidFromCode(String code) {
-        WeChatSessionInfo sessionInfo = weChatMiniProgramUtil.code2Session(code);
-        if (sessionInfo == null || sessionInfo.getErrcode() != null) {
-            Integer errcode = sessionInfo != null ? sessionInfo.getErrcode() : null;
-            String errmsg = sessionInfo != null ? sessionInfo.getErrmsg() : "调用微信接口失败";
-            log.error("登录失败:code2session 失败, errcode={}, errmsg={}", errcode, errmsg);
-            return null;
-        }
-
-        String openid = sessionInfo.getOpenid();
-        if (StringUtils.isBlank(openid)) {
-            log.error("登录失败:无法获取 openid");
-            return null;
-        }
-        log.info("成功获取 openid: {}", maskString(openid, 8));
-        return openid;
-    }
-
-    /**
-     * 查找或创建用户
-     * 规则:只要 user_phone 存在,就代表存在账号,不创建新账号
-     * 
-     * @param openid 微信OpenID
-     * @param phone 解析后的手机号(如果为null,说明没有提供phoneCode或解析失败)
-     */
-    private LifeUser findOrCreateUser(String openid, String phone) {
-        LifeUser user = null;
-        
-        // 1. 如果提供了手机号,优先通过手机号查找(只要手机号存在就代表账号存在)
-        if (StringUtils.isNotBlank(phone)) {
-            user = findUserByPhone(phone);
-            if (user != null) {
-                // 账号已存在,建立 openid 和 userId 的映射关系
-                saveOpenidMapping(openid, user.getId());
-                log.info("通过手机号找到已存在账号: phone={}, userId={}, openid={}", 
-                        maskString(phone, 7), user.getId(), maskString(openid, 8));
-                // 如果用户已有手机号,但新解析的手机号不同,更新手机号
-                if (StringUtils.isNotBlank(user.getUserPhone()) && !user.getUserPhone().equals(phone)) {
-                    log.info("检测到手机号变更,更新手机号: userId={}, oldPhone={}, newPhone={}", 
-                            user.getId(), maskString(user.getUserPhone(), 7), maskString(phone, 7));
-                    updateUserPhone(user, phone);
-                }
-                return user;
-            }
-        }
-        
-        // 2. 如果通过手机号找不到(或未提供手机号),尝试通过 openid 查找
-        user = findUserByOpenid(openid);
-        
-        // 3. 如果通过 openid 找到了用户,且提供了手机号,更新手机号
-        if (user != null) {
-            if (StringUtils.isNotBlank(phone) && StringUtils.isBlank(user.getUserPhone())) {
-                // 用户存在但没有手机号,更新手机号
-                updateUserPhone(user, phone);
-            } else if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(user.getUserPhone()) 
-                    && !user.getUserPhone().equals(phone)) {
-                // 用户已有手机号,但新解析的手机号不同,也更新
-                log.info("检测到手机号变更,更新手机号: userId={}, oldPhone={}, newPhone={}", 
-                        user.getId(), maskString(user.getUserPhone(), 7), maskString(phone, 7));
-                updateUserPhone(user, phone);
-            }
-            return user;
-        }
-
-        // 4. 如果都找不到,且未提供手机号(或手机号不存在),才创建新账号
-        // 注意:如果提供了手机号但找不到,说明这个手机号没有注册过,可以创建新账号
-        user = createNewUser(openid, phone);
-        if (user != null) {
-            saveOpenidMapping(openid, user.getId());
-        }
-
-        return user;
-    }
-
-    /**
-     * 通过 openid 查找用户
-     */
-    private LifeUser findUserByOpenid(String openid) {
-        String openidKey = REDIS_KEY_OPENID_PREFIX + openid;
-        String userIdStr = baseRedisService.getString(openidKey);
-        
-        if (StringUtils.isBlank(userIdStr)) {
-            return null;
-        }
-
-        try {
-            Integer userId = Integer.parseInt(userIdStr);
-            LifeUser user = lifeUserMapper.selectById(userId);
-            if (user != null) {
-                log.info("通过 openid 找到用户: openid={}, userId={}", maskString(openid, 8), userId);
-            }
-            return user;
-        } catch (NumberFormatException e) {
-            log.warn("Redis 中的 userId 格式错误: {}", userIdStr);
-            return null;
-        }
-    }
-
-    /**
-     * 通过手机号查找用户
-     */
-    private LifeUser findUserByPhone(String phone) {
-        LambdaQueryWrapper<LifeUser> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(LifeUser::getUserPhone, phone);
-        LifeUser user = lifeUserMapper.selectOne(queryWrapper);
-        if (user != null) {
-            log.info("通过手机号找到用户: phone={}, userId={}", maskString(phone, 7), user.getId());
-        }
-        return user;
-    }
-
-    /**
-     * 创建新用户
-     */
-    private LifeUser createNewUser(String openid, String phone) {
-        LifeUser user = new LifeUser();
-        if (StringUtils.isNotBlank(phone)) {
-            user.setUserPhone(phone);
-            user.setUserName(phone);
-            user.setRealName(phone);
-        } else {
-            // 没有手机号时,使用 openid 后8位作为临时用户名
-            String tempName = "微信用户" + openid.substring(Math.max(0, openid.length() - 8));
-            user.setUserName(tempName);
-            user.setRealName(tempName);
-        }
-        user.setCreatedTime(new Date());
-        
-        int ret = lifeUserMapper.insert(user);
-        if (ret != 1) {
-            log.error("创建用户失败");
-            return null;
-        }
-        
-        // MyBatis-Plus 的 insert 会自动填充 ID,不需要重新查询
-        log.info("创建新用户: openid={}, userId={}, phone={}", maskString(openid, 8), user.getId(), maskString(phone, 7));
-        return user;
-    }
-
-    /**
-     * 更新用户手机号
-     */
-    private void updateUserPhone(LifeUser user, String phone) {
-        user.setUserPhone(phone);
-        if (StringUtils.isBlank(user.getUserName()) || user.getUserName().startsWith("微信用户")) {
-            user.setUserName(phone);
-        }
-        if (StringUtils.isBlank(user.getRealName()) || user.getRealName().startsWith("微信用户")) {
-            user.setRealName(phone);
-        }
-        user.setUpdatedTime(new Date());
-        lifeUserMapper.updateById(user);
-        log.info("更新用户手机号: userId={}, phone={}", user.getId(), maskString(phone, 7));
-    }
-
-    /**
-     * 保存 openid 和 userId 的映射关系
-     */
-    private void saveOpenidMapping(String openid, Integer userId) {
-        String openidKey = REDIS_KEY_OPENID_PREFIX + openid;
-        baseRedisService.setString(openidKey, userId.toString(), OPENID_MAPPING_EXPIRE_SECONDS);
-    }
-
-    /**
-     * 检查用户状态是否有效
-     */
-    private boolean isUserValid(LifeUser user) {
-        if (user.getIsBanned() != null && user.getIsBanned() == 1) {
-            log.warn("用户已被封禁: userId={}", user.getId());
-            return false;
-        }
-        if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
-            log.warn("用户已注销: userId={}", user.getId());
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * 生成并存储 token
-     * @param openid 微信 openid
-     * @param user 用户实体(可能尚未持久化手机号)
-     * @param currentLoginPhone 本次登录解析到的手机号(可选),有则优先用其写入 miniprogram_user_{phone},避免只存 openid 不存 phone 的情况
-     */
-    private String generateAndStoreToken(String openid, LifeUser user, String currentLoginPhone) {
-        // 构建 token 信息
-        Map<String, String> tokenMap = buildTokenMap(openid, user);
-        String userName = StringUtils.isNotBlank(user.getUserName()) ? user.getUserName() : "用户";
-        String token = generateToken(openid, userName, tokenMap);
-
-        // 存入 Redis(使用 openid 作为 key,始终写入)
-        baseRedisService.setString(REDIS_KEY_TOKEN_PREFIX + openid, token, TOKEN_EXPIRE_SECONDS);
-
-        // 兼容旧版本:有手机号则同时按手机号存一份(优先用本次登录解析到的手机号,否则用用户实体中的手机号)
-        String phoneToStore = StringUtils.isNotBlank(currentLoginPhone) ? currentLoginPhone : user.getUserPhone();
-        if (StringUtils.isNotBlank(phoneToStore)) {
-            baseRedisService.setString(REDIS_KEY_USER_PHONE_PREFIX + phoneToStore, token, TOKEN_EXPIRE_SECONDS);
-        }
-
-        return token;
-    }
-
-    /**
-     * 构建 token 信息 Map
-     */
-    private Map<String, String> buildTokenMap(String openid, LifeUser user) {
-        Map<String, String> tokenMap = new HashMap<>();
-        tokenMap.put("openid", openid);
-        tokenMap.put("phone", StringUtils.isNotBlank(user.getUserPhone()) ? user.getUserPhone() : "");
-        tokenMap.put("userName", StringUtils.isNotBlank(user.getUserName()) ? user.getUserName() : "用户");
-        tokenMap.put("userId", user.getId().toString());
-        tokenMap.put("userType", "miniprogram_user");
-        return tokenMap;
-    }
-
-    /**
-     * 构建返回对象
-     */
-    private DiningUserVo buildDiningUserVo(LifeUser user, String token, String openid) {
-        DiningUserVo diningUserVo = new DiningUserVo();
-        diningUserVo.setId(user.getId().longValue());
-        // 优先使用 user 对象中的手机号(如果通过 phoneCode 解析并更新了,这里会是最新的)
-        diningUserVo.setPhone(user.getUserPhone());
-        diningUserVo.setNickName(user.getUserName());
-        diningUserVo.setAvatarUrl(user.getUserImage());
-        diningUserVo.setStatus(0);
-        diningUserVo.setCreatedTime(user.getCreatedTime());
-        diningUserVo.setToken(token);
-        diningUserVo.setOpenId(openid);
-        return diningUserVo;
-    }
-    
-    /**
-     * 构建返回对象(带解析后的手机号)
-     */
-    private DiningUserVo buildDiningUserVo(LifeUser user, String token, String openid, String parsedPhone) {
-        DiningUserVo diningUserVo = buildDiningUserVo(user, token, openid);
-        // 如果解析到了手机号,优先使用解析后的手机号返回给前端
-        if (StringUtils.isNotBlank(parsedPhone)) {
-            diningUserVo.setPhone(parsedPhone);
-        }
-        return diningUserVo;
-    }
-
-    /**
-     * 掩码字符串(用于日志脱敏)
-     */
-    private String maskString(String str, int visibleLength) {
-        if (StringUtils.isBlank(str) || str.length() <= visibleLength) {
-            return "****";
-        }
-        return str.substring(0, Math.min(visibleLength, str.length())) + "****";
-    }
-
-    private String generateToken(String userId, String userName, Map<String, String> tokenMap) {
-        int effectiveTimeInt = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
-        String effectiveTimeUnit = effectiveTime.substring(effectiveTime.length() - 1);
-        long effectiveTimeIntLong = 0L;
-        switch (effectiveTimeUnit) {
-            case "s":
-                effectiveTimeIntLong = effectiveTimeInt * 1000L;
-                break;
-            case "m":
-                effectiveTimeIntLong = effectiveTimeInt * 60L * 1000L;
-                break;
-            case "h":
-                effectiveTimeIntLong = effectiveTimeInt * 60L * 60L * 1000L;
-                break;
-            case "d":
-                effectiveTimeIntLong = effectiveTimeInt * 24L * 60L * 60L * 1000L;
-                break;
-            default:
-                effectiveTimeIntLong = effectiveTimeInt * 24L * 60L * 60L * 1000L;
-        }
-        return JwtUtil.createJWT("user_" + userId, userName, JSONObject.toJSONString(tokenMap), effectiveTimeIntLong);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public DiningUserVo updateProfile(UserProfileUpdateDto dto) {
-        // 1. 查询用户是否存在
-        LifeUser user = lifeUserMapper.selectById(dto.getUserId().intValue());
-        if (user == null) {
-            log.warn("更新个人信息失败:用户不存在, userId={}", dto.getUserId());
-            return null;
-        }
-
-        // 2. 获取当前用户ID(用于设置 updatedUserId)
-        Integer currentUserId = TokenUtil.getCurrentUserId();
-        if (currentUserId == null) {
-            currentUserId = dto.getUserId().intValue(); // 如果没有 token,使用被更新的用户ID
-        }
-
-        // 3. 使用 LambdaUpdateWrapper 只更新需要更新的字段,避免更新不应该更新的字段
-        LambdaUpdateWrapper<LifeUser> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(LifeUser::getId, dto.getUserId().intValue());
-
-        // 只更新非空字段
-        if (StringUtils.isNotBlank(dto.getNickName())) {
-            updateWrapper.set(LifeUser::getUserName, dto.getNickName());
-        }
-        if (StringUtils.isNotBlank(dto.getAvatarUrl())) {
-            updateWrapper.set(LifeUser::getUserImage, dto.getAvatarUrl());
-        }
-        if (StringUtils.isNotBlank(dto.getGender())) {
-            updateWrapper.set(LifeUser::getUserSex, dto.getGender());
-        }
-        if (dto.getBirthday() != null) {
-            updateWrapper.set(LifeUser::getUserBirthday, dto.getBirthday());
-        }
-        if (StringUtils.isNotBlank(dto.getRealName())) {
-            updateWrapper.set(LifeUser::getRealName, dto.getRealName());
-        }
-        if (StringUtils.isNotBlank(dto.getProvince())) {
-            updateWrapper.set(LifeUser::getProvince, dto.getProvince());
-        }
-        if (StringUtils.isNotBlank(dto.getCity())) {
-            updateWrapper.set(LifeUser::getCity, dto.getCity());
-        }
-        if (StringUtils.isNotBlank(dto.getDistrict())) {
-            updateWrapper.set(LifeUser::getDistrict, dto.getDistrict());
-        }
-        if (StringUtils.isNotBlank(dto.getAddress())) {
-            updateWrapper.set(LifeUser::getAddress, dto.getAddress());
-        }
-        if (StringUtils.isNotBlank(dto.getJianjie())) {
-            updateWrapper.set(LifeUser::getJianjie, dto.getJianjie());
-        }
-
-        // 设置更新时间和更新人ID
-        updateWrapper.set(LifeUser::getUpdatedTime, new Date());
-        updateWrapper.set(LifeUser::getUpdatedUserId, currentUserId);
-
-        // 4. 执行更新
-        int result = lifeUserMapper.update(null, updateWrapper);
-        if (result != 1) {
-            log.error("更新用户信息失败, userId={}", dto.getUserId());
-            return null;
-        }
-        log.info("用户信息更新成功, userId={}, updatedUserId={}", dto.getUserId(), currentUserId);
-
-        // 5. 重新查询用户信息(因为使用 updateWrapper 后,user 对象不会自动更新)
-        LifeUser updatedUser = lifeUserMapper.selectById(dto.getUserId().intValue());
-        if (updatedUser == null) {
-            log.error("更新后查询用户信息失败, userId={}", dto.getUserId());
-            return null;
-        }
-
-        // 6. 返回更新后的用户信息
-        return buildDiningUserVo(updatedUser);
-    }
-
-    @Override
-    public DiningUserVo getUserInfo(Long userId) {
-        // 1. 查询用户
-        LifeUser user = lifeUserMapper.selectById(userId.intValue());
-        if (user == null) {
-            log.warn("获取用户信息失败:用户不存在, userId={}", userId);
-            return null;
-        }
-
-        // 2. 检查用户状态
-        if (user.getIsBanned() != null && user.getIsBanned() == 1) {
-            log.warn("用户已被封禁: userId={}", userId);
-            return null;
-        }
-        if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
-            log.warn("用户已注销: userId={}", userId);
-            return null;
-        }
-
-        // 3. 返回用户信息
-        return buildDiningUserVo(user);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public DiningUserVo changePhone(ChangePhoneDto dto) {
-        String newPhone = dto.getNewPhone().trim();
-        String codeStr = dto.getCode().trim();
-
-        // 1. 校验验证码(Feign 调 store ali/checkSmsCode,appType=0 用户端,businessType=3 修改手机号)
-        int codeInt;
-        try {
-            codeInt = Integer.parseInt(codeStr);
-        } catch (NumberFormatException e) {
-            log.warn("更换手机号失败:验证码格式错误, userId={}, newPhone={}", dto.getUserId(), newPhone);
-            return null;
-        }
-        R<?> checkRes = alienStoreFeign.checkSmsCode(newPhone, 0, 3, codeInt);
-        if (!R.isSuccess(checkRes)) {
-            log.warn("更换手机号失败:验证码错误或已过期, userId={}, newPhone={}", dto.getUserId(), newPhone);
-            return null;
-        }
-
-        // 2. 查询用户
-        LifeUser user = lifeUserMapper.selectById(dto.getUserId().intValue());
-        if (user == null) {
-            log.warn("更换手机号失败:用户不存在, userId={}", dto.getUserId());
-            return null;
-        }
-        if (user.getIsBanned() != null && user.getIsBanned() == 1) {
-            log.warn("更换手机号失败:用户已被封禁, userId={}", dto.getUserId());
-            return null;
-        }
-        if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
-            log.warn("更换手机号失败:用户已注销, userId={}", dto.getUserId());
-            return null;
-        }
-
-        // 3. 新手机号与当前相同则无需更新
-        if (newPhone.equals(user.getUserPhone())) {
-            log.info("新手机号与当前相同,无需更换, userId={}", dto.getUserId());
-            return buildDiningUserVo(user);
-        }
-
-        // 4. 新手机号是否已被其他用户使用
-        LambdaQueryWrapper<LifeUser> q = new LambdaQueryWrapper<>();
-        q.eq(LifeUser::getUserPhone, newPhone);
-        LifeUser existing = lifeUserMapper.selectOne(q);
-        if (existing != null && !existing.getId().equals(user.getId())) {
-            log.warn("更换手机号失败:新手机号已被其他用户使用, newPhone={}", newPhone);
-            return null;
-        }
-
-        // 5. 更新 user_phone
-        String oldPhone = user.getUserPhone();
-        user.setUserPhone(newPhone);
-        user.setUpdatedTime(new Date());
-        int n = lifeUserMapper.updateById(user);
-        if (n != 1) {
-            log.error("更换手机号失败:更新数据库异常, userId={}", dto.getUserId());
-            return null;
-        }
-
-        // 6. 只清除小程序旧手机号对应的 token,APP 的 token 保持不变
-        // 因为小程序更换手机号只影响小程序平台,APP 可以继续使用旧手机号登录
-        baseRedisService.delete(REDIS_KEY_USER_PHONE_PREFIX + oldPhone);
-        log.info("更换手机号成功, userId={}, oldPhone={}, newPhone={}(仅清除小程序 token,APP token 保持不变)", dto.getUserId(), oldPhone, newPhone);
-
-        return buildDiningUserVo(user);
-    }
-
-    @Override
-    public TokenVerifyVo verifyToken(String token) {
-        TokenVerifyVo verifyVo = new TokenVerifyVo();
-        verifyVo.setValid(false);
-
-        // 1. 检查 token 是否为空
-        if (StringUtils.isBlank(token)) {
-            verifyVo.setReason("Token 不能为空");
-            return verifyVo;
-        }
-
-        // 去除 "Bearer " 前缀(不区分大小写)
-        token = token.trim();
-        if (token.length() > 7 && token.substring(0, 7).equalsIgnoreCase("Bearer ")) {
-            token = token.substring(7).trim();
-        }
-        
-        if (StringUtils.isBlank(token)) {
-            verifyVo.setReason("Token 去除前缀后为空");
-            return verifyVo;
-        }
-
-        try {
-            // 2. 解析 token,验证格式和签名
-            Claims claims = JwtUtil.parseJWT(token);
-            
-            // 3. 检查 token 是否过期
-            Date expiration = claims.getExpiration();
-            if (expiration != null && expiration.before(new Date())) {
-                verifyVo.setReason("Token 已过期");
-                verifyVo.setExpirationTime(expiration);
-                return verifyVo;
-            }
-
-            // 4. 从 token 中提取用户信息
-            String sub = claims.get("sub").toString();
-            JSONObject tokenInfo = JSONObject.parseObject(sub);
-            String openid = tokenInfo.getString("openid");
-            String phone = tokenInfo.getString("phone");
-            String userIdStr = tokenInfo.getString("userId");
-            String userName = tokenInfo.getString("userName");
-
-            // 5. 验证 Redis 中是否存在该 token(使用小程序专用的 key 前缀)
-            boolean tokenExists = false;
-            if (StringUtils.isNotBlank(openid)) {
-                // 优先使用 openid 查找
-                String redisToken = baseRedisService.getString(REDIS_KEY_TOKEN_PREFIX + openid);
-                if (token.equals(redisToken)) {
-                    tokenExists = true;
-                }
-            }
-            
-            // 兼容旧版本:通过手机号查找
-            if (!tokenExists && StringUtils.isNotBlank(phone)) {
-                String redisToken = baseRedisService.getString(REDIS_KEY_USER_PHONE_PREFIX + phone);
-                if (token.equals(redisToken)) {
-                    tokenExists = true;
-                }
-            }
-
-            if (!tokenExists) {
-                verifyVo.setReason("Token 不存在或已失效(可能已退出登录)");
-                return verifyVo;
-            }
-
-            // 6. 验证用户状态(如果提供了 userId)
-            if (StringUtils.isNotBlank(userIdStr)) {
-                try {
-                    Integer userId = Integer.parseInt(userIdStr);
-                    LifeUser user = lifeUserMapper.selectById(userId);
-                    if (user == null) {
-                        verifyVo.setReason("用户不存在");
-                        return verifyVo;
-                    }
-                    if (user.getIsBanned() != null && user.getIsBanned() == 1) {
-                        verifyVo.setReason("用户已被封禁");
-                        return verifyVo;
-                    }
-                    if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
-                        verifyVo.setReason("用户已注销");
-                        return verifyVo;
-                    }
-                } catch (NumberFormatException e) {
-                    log.warn("Token 中的 userId 格式错误: {}", userIdStr);
-                }
-            }
-
-            // 7. Token 验证通过,返回用户信息
-            verifyVo.setValid(true);
-            if (StringUtils.isNotBlank(userIdStr)) {
-                try {
-                    verifyVo.setUserId(Long.parseLong(userIdStr));
-                } catch (NumberFormatException e) {
-                    log.warn("无法解析 userId: {}", userIdStr);
-                }
-            }
-            verifyVo.setPhone(phone);
-            verifyVo.setNickName(userName);
-            verifyVo.setOpenid(openid);
-            verifyVo.setExpirationTime(expiration);
-
-            log.info("Token 验证成功: userId={}, openid={}, phone={}", userIdStr, openid, phone);
-            return verifyVo;
-
-        } catch (ExpiredJwtException e) {
-            log.warn("Token 已过期: {}", e.getMessage());
-            verifyVo.setReason("Token 已过期: " + e.getMessage());
-            return verifyVo;
-        } catch (MalformedJwtException e) {
-            log.warn("Token 格式错误: {}", e.getMessage());
-            verifyVo.setReason("Token 格式错误: " + e.getMessage());
-            return verifyVo;
-        } catch (SignatureException e) {
-            log.warn("Token 签名验证失败: {}", e.getMessage());
-            verifyVo.setReason("Token 签名验证失败: " + e.getMessage());
-            return verifyVo;
-        } catch (Exception e) {
-            log.error("Token 验证异常: {}", e.getMessage(), e);
-            verifyVo.setReason("Token 验证异常: " + e.getMessage());
-            return verifyVo;
-        }
-    }
-
-    /**
-     * 构建 DiningUserVo
-     */
-    private DiningUserVo buildDiningUserVo(LifeUser user) {
-        DiningUserVo diningUserVo = new DiningUserVo();
-        diningUserVo.setId(user.getId().longValue());
-        diningUserVo.setPhone(user.getUserPhone());
-        diningUserVo.setNickName(user.getUserName());
-        diningUserVo.setAvatarUrl(user.getUserImage());
-        diningUserVo.setStatus(0);
-        diningUserVo.setCreatedTime(user.getCreatedTime());
-        // 补充更多字段
-        diningUserVo.setGender(user.getUserSex());
-        diningUserVo.setBirthday(user.getUserBirthday());
-        diningUserVo.setRealName(user.getRealName());
-        diningUserVo.setProvince(user.getProvince());
-        diningUserVo.setCity(user.getCity());
-        diningUserVo.setDistrict(user.getDistrict());
-        diningUserVo.setAddress(user.getAddress());
-        diningUserVo.setJianjie(user.getJianjie());
-        return diningUserVo;
-    }
-}

+ 0 - 118
alien-store/src/main/java/shop/alien/store/service/impl/OrderLockServiceImpl.java

@@ -1,118 +0,0 @@
-package shop.alien.store.service.impl;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-import shop.alien.store.config.BaseRedisService;
-import shop.alien.store.service.OrderLockService;
-
-/**
- * 订单锁定服务实现类
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class OrderLockServiceImpl implements OrderLockService {
-
-    private static final String ORDER_LOCK_KEY_PREFIX = "order:lock:table:";
-    private static final String SETTLEMENT_LOCK_KEY_PREFIX = "settlement:lock:order:";
-    private static final int ORDER_LOCK_EXPIRE_SECONDS = 300; // 5分钟过期
-
-    private final BaseRedisService baseRedisService;
-
-    @Override
-    public boolean lockOrder(Integer tableId, Integer userId) {
-        log.info("锁定订单, tableId={}, userId={}", tableId, userId);
-
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock)) {
-            // 已锁定,检查是否是当前用户
-            if (existingLock.equals(String.valueOf(userId))) {
-                // 刷新过期时间
-                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
-                return true;
-            } else {
-                // 被其他用户锁定
-                return false;
-            }
-        }
-
-        // 设置锁定
-        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
-        return true;
-    }
-
-    @Override
-    public void unlockOrder(Integer tableId, Integer userId) {
-        log.info("解锁订单, tableId={}, userId={}", tableId, userId);
-
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
-            baseRedisService.delete(lockKey);
-        }
-    }
-
-    @Override
-    public Integer checkOrderLock(Integer tableId) {
-        String lockKey = ORDER_LOCK_KEY_PREFIX + tableId;
-        String lockUserId = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(lockUserId)) {
-            try {
-                return Integer.parseInt(lockUserId);
-            } catch (NumberFormatException e) {
-                return null;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean lockSettlement(Integer orderId, Integer userId) {
-        log.info("锁定订单结算, orderId={}, userId={}", orderId, userId);
-
-        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock)) {
-            if (existingLock.equals(String.valueOf(userId))) {
-                baseRedisService.setString(lockKey, existingLock, (long) ORDER_LOCK_EXPIRE_SECONDS);
-                return true;
-            } else {
-                return false;
-            }
-        }
-
-        baseRedisService.setString(lockKey, String.valueOf(userId), (long) ORDER_LOCK_EXPIRE_SECONDS);
-        return true;
-    }
-
-    @Override
-    public void unlockSettlement(Integer orderId, Integer userId) {
-        log.info("解锁订单结算, orderId={}, userId={}", orderId, userId);
-
-        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
-        String existingLock = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(existingLock) && existingLock.equals(String.valueOf(userId))) {
-            baseRedisService.delete(lockKey);
-        }
-    }
-
-    @Override
-    public Integer checkSettlementLock(Integer orderId) {
-        String lockKey = SETTLEMENT_LOCK_KEY_PREFIX + orderId;
-        String lockUserId = baseRedisService.getString(lockKey);
-        if (StringUtils.hasText(lockUserId)) {
-            try {
-                return Integer.parseInt(lockUserId);
-            } catch (NumberFormatException e) {
-                return null;
-            }
-        }
-        return null;
-    }
-}

+ 0 - 239
alien-store/src/main/java/shop/alien/store/service/impl/ScanOrderStoreInfoServiceImpl.java

@@ -1,239 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.alibaba.fastjson.JSON;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import shop.alien.entity.store.StoreCuisine;
-import shop.alien.entity.store.StoreCuisineCategory;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StoreTable;
-import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
-import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
-import shop.alien.mapper.StoreCuisineCategoryMapper;
-import shop.alien.mapper.StoreCuisineMapper;
-import shop.alien.mapper.StoreInfoMapper;
-import shop.alien.mapper.StoreTableMapper;
-import shop.alien.store.service.ScanOrderStoreInfoService;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 门店信息查询服务实现类
- *
- * @author system
- * @since 2025-02-02
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class ScanOrderStoreInfoServiceImpl implements ScanOrderStoreInfoService {
-
-    private final StoreTableMapper storeTableMapper;
-    private final StoreCuisineCategoryMapper storeCuisineCategoryMapper;
-    private final StoreCuisineMapper storeCuisineMapper;
-    private final StoreInfoMapper storeInfoMapper;
-
-    @Override
-    public List<StoreTable> getTablesByStoreId(Integer storeId) {
-        log.info("根据门店ID查询桌号列表, storeId={}", storeId);
-        
-        LambdaQueryWrapper<StoreTable> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreTable::getStoreId, storeId);
-        wrapper.eq(StoreTable::getDeleteFlag, 0);
-        wrapper.orderByAsc(StoreTable::getTableNumber);
-        
-        return storeTableMapper.selectList(wrapper);
-    }
-
-    @Override
-    public List<StoreCuisineCategory> getCategoriesByStoreId(Integer storeId) {
-        log.info("根据门店ID查询菜品种类列表, storeId={}", storeId);
-        
-        LambdaQueryWrapper<StoreCuisineCategory> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisineCategory::getStoreId, storeId);
-        wrapper.eq(StoreCuisineCategory::getDeleteFlag, 0);
-        wrapper.eq(StoreCuisineCategory::getStatus, 1); // 只查询启用的分类
-        wrapper.orderByAsc(StoreCuisineCategory::getSort); // 按排序字段排序
-        
-        return storeCuisineCategoryMapper.selectList(wrapper);
-    }
-
-    @Override
-    public List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId) {
-        log.info("根据菜品种类ID查询菜品信息列表, categoryId={}", categoryId);
-        
-        // 先查询分类信息,获取 storeId
-        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
-        if (category == null) {
-            log.warn("菜品种类不存在, categoryId={}", categoryId);
-            return new java.util.ArrayList<>();
-        }
-        
-        // 查询该门店下所有上架的菜品(与 getCategoriesWithCuisinesByStoreId 中 cuisines 查询条件、排序一致)
-        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisine::getStoreId, category.getStoreId());
-        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 只查询上架的菜品
-        wrapper.orderByAsc(StoreCuisine::getId); // 与 categories-with-cuisines 中 cuisines 顺序一致
-        
-        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
-        
-        // 过滤出包含该分类ID的菜品
-        // categoryIds 是 JSON 数组格式,如:[1,2,3]
-        return allCuisines.stream()
-                .filter(cuisine -> {
-                    String categoryIdsStr = cuisine.getCategoryIds();
-                    if (StringUtils.isBlank(categoryIdsStr)) {
-                        return false;
-                    }
-                    try {
-                        // 解析 JSON 数组
-                        List<Integer> categoryIds = JSON.parseArray(categoryIdsStr, Integer.class);
-                        return categoryIds != null && categoryIds.contains(categoryId);
-                    } catch (Exception e) {
-                        log.warn("解析菜品分类IDs失败, cuisineId={}, categoryIds={}, error={}", 
-                                cuisine.getId(), categoryIdsStr, e.getMessage());
-                        // 如果解析失败,使用简单的字符串匹配作为降级方案
-                        return categoryIdsStr.contains(String.valueOf(categoryId));
-                    }
-                })
-                .collect(Collectors.toList());
-    }
-
-    @Override
-    public List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId, String keyword) {
-        log.info("根据门店ID查询菜品种类及下属菜品, storeId={}, keyword={}", storeId, keyword);
-        List<StoreCuisineCategory> categories = getCategoriesByStoreId(storeId);
-        if (categories == null || categories.isEmpty()) {
-            return new ArrayList<>();
-        }
-        // 与 getCuisinesByCategoryId 相同的查询条件与排序,保证 cuisines 字段与 /store/info/cuisines 一致
-        LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
-        cuisineWrapper.eq(StoreCuisine::getStoreId, storeId);
-        cuisineWrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        cuisineWrapper.eq(StoreCuisine::getShelfStatus, 1);
-        cuisineWrapper.orderByAsc(StoreCuisine::getId);
-        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(cuisineWrapper);
-        if (allCuisines == null) {
-            allCuisines = new ArrayList<>();
-        }
-        boolean filterByName = StringUtils.isNotBlank(keyword);
-        String keywordLower = filterByName ? keyword.trim().toLowerCase() : null;
-        List<CategoryWithCuisinesVO> result = new ArrayList<>();
-        for (StoreCuisineCategory category : categories) {
-            Integer categoryId = category.getId();
-            List<StoreCuisine> cuisines = allCuisines.stream()
-                    .filter(c -> belongsToCategory(c, categoryId))
-                    .filter(c -> !filterByName || (c.getName() != null && c.getName().toLowerCase().contains(keywordLower)))
-                    .collect(Collectors.toList());
-            result.add(new CategoryWithCuisinesVO(category, cuisines));
-        }
-        return result;
-    }
-
-    private boolean belongsToCategory(StoreCuisine cuisine, Integer categoryId) {
-        String categoryIdsStr = cuisine.getCategoryIds();
-        if (StringUtils.isBlank(categoryIdsStr)) {
-            return false;
-        }
-        try {
-            List<Integer> categoryIds = JSON.parseArray(categoryIdsStr, Integer.class);
-            return categoryIds != null && categoryIds.contains(categoryId);
-        } catch (Exception e) {
-            return categoryIdsStr.contains(String.valueOf(categoryId));
-        }
-    }
-
-    @Override
-    public boolean deleteCategory(Integer categoryId) {
-        log.info("删除菜品种类(仅解除绑定+逻辑删分类), categoryId={}", categoryId);
-        if (categoryId == null) {
-            log.warn("删除菜品种类失败:分类ID为空");
-            return false;
-        }
-        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
-        if (category == null) {
-            log.warn("删除菜品种类失败:分类不存在, categoryId={}", categoryId);
-            return false;
-        }
-        Integer storeId = category.getStoreId();
-        // 1. 解除绑定:将该分类ID从所有关联菜品的 category_ids 中移除,价目表菜品其它字段不变
-        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisine::getStoreId, storeId);
-        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
-        if (allCuisines != null) {
-            for (StoreCuisine cuisine : allCuisines) {
-                if (!belongsToCategory(cuisine, categoryId)) {
-                    continue;
-                }
-                String newCategoryIds = removeCategoryIdFromJson(cuisine.getCategoryIds(), categoryId);
-                cuisine.setCategoryIds(newCategoryIds);
-                storeCuisineMapper.updateById(cuisine);
-            }
-        }
-        // 2. 逻辑删除菜品种类
-        storeCuisineCategoryMapper.deleteById(categoryId);
-        log.info("删除菜品种类完成, categoryId={}", categoryId);
-        return true;
-    }
-
-    /** 从 categoryIds 的 JSON 数组中移除指定 categoryId,返回新 JSON 字符串;若为空则返回 null */
-    private String removeCategoryIdFromJson(String categoryIdsStr, Integer categoryId) {
-        if (StringUtils.isBlank(categoryIdsStr)) {
-            return null;
-        }
-        try {
-            List<Integer> list = JSON.parseArray(categoryIdsStr, Integer.class);
-            if (list == null || list.isEmpty()) {
-                return null;
-            }
-            list.remove(categoryId);
-            if (list.isEmpty()) {
-                return null;
-            }
-            return JSON.toJSONString(list);
-        } catch (Exception e) {
-            log.warn("解析 categoryIds 失败, categoryIdsStr={}, 原样返回", categoryIdsStr, e);
-            return categoryIdsStr;
-        }
-    }
-
-    @Override
-    public StoreInfoWithHomepageCuisinesDTO getStoreInfoWithHomepageCuisines(Integer storeId) {
-        log.info("根据商铺ID查询店铺信息和首页展示美食价目表, storeId={}", storeId);
-        
-        // 1. 查询店铺信息
-        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
-        if (storeInfo == null) {
-            throw new RuntimeException("店铺不存在");
-        }
-        
-        // 2. 查询首页展示的美食价目表(is_homepage_display = 1,上架状态 = 1,审核通过 = 1)
-        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreCuisine::getStoreId, storeId);
-        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
-        wrapper.eq(StoreCuisine::getIsHomepageDisplay, 1); // 首页展示
-        wrapper.eq(StoreCuisine::getShelfStatus, 1); // 上架状态
-        wrapper.eq(StoreCuisine::getStatus, 1); // 审核通过
-        wrapper.orderByDesc(StoreCuisine::getCreatedTime); // 按创建时间倒序
-        
-        List<StoreCuisine> homepageCuisines = storeCuisineMapper.selectList(wrapper);
-        if (homepageCuisines == null) {
-            homepageCuisines = new ArrayList<>();
-        }
-        
-        // 3. 构建返回DTO
-        StoreInfoWithHomepageCuisinesDTO dto = new StoreInfoWithHomepageCuisinesDTO();
-        dto.setStoreInfo(storeInfo);
-        dto.setHomepageCuisines(homepageCuisines);
-        
-        log.info("查询完成, storeId={}, 首页展示美食数量={}", storeId, homepageCuisines.size());
-        return dto;
-    }
-}

+ 0 - 180
alien-store/src/main/java/shop/alien/store/service/impl/SseServiceImpl.java

@@ -1,180 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.alibaba.fastjson2.JSON;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-import java.io.IOException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * SSE推送服务实现类
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Service
-public class SseServiceImpl implements shop.alien.store.service.SseService {
-
-    // 存储每个桌号的SSE连接,一个桌号可以有多个连接(多个用户)
-    private final ConcurrentHashMap<Integer, ConcurrentHashMap<String, SseEmitter>> connections = new ConcurrentHashMap<>();
-
-    // 定时任务执行器,用于发送心跳
-    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
-
-    @Override
-    public SseEmitter createConnection(Integer tableId) {
-        log.info("创建SSE连接, tableId={}", tableId);
-
-        // 创建SSE连接,设置超时时间为30分钟
-        SseEmitter emitter = new SseEmitter(30 * 60 * 1000L);
-
-        // 生成连接ID
-        String connectionId = "conn_" + System.currentTimeMillis() + "_" + Thread.currentThread().getId();
-
-        // 存储连接
-        connections.computeIfAbsent(tableId, k -> new ConcurrentHashMap<>()).put(connectionId, emitter);
-
-        // 设置完成和超时回调
-        emitter.onCompletion(() -> {
-            log.info("SSE连接完成, tableId={}, connectionId={}", tableId, connectionId);
-            removeConnection(tableId, connectionId);
-        });
-
-        emitter.onTimeout(() -> {
-            log.info("SSE连接超时, tableId={}, connectionId={}", tableId, connectionId);
-            removeConnection(tableId, connectionId);
-        });
-
-        emitter.onError((ex) -> {
-            if (isClientDisconnect(ex)) {
-                log.info("SSE客户端已断开, tableId={}, connectionId={}", tableId, connectionId);
-            } else {
-                log.error("SSE连接错误, tableId={}, connectionId={}, error={}", tableId, connectionId, ex.getMessage(), ex);
-            }
-            removeConnection(tableId, connectionId);
-        });
-
-        // 发送初始连接成功消息
-        try {
-            emitter.send(SseEmitter.event()
-                    .name("connected")
-                    .data("连接成功"));
-        } catch (IOException e) {
-            log.error("发送初始消息失败, tableId={}, connectionId={}", tableId, connectionId, e);
-            removeConnection(tableId, connectionId);
-            return null;
-        }
-
-        // 启动心跳任务
-        startHeartbeat(tableId, connectionId, emitter);
-
-        return emitter;
-    }
-
-    @Override
-    public void pushCartUpdate(Integer tableId, Object message) {
-        log.info("推送购物车更新, tableId={}", tableId);
-        ConcurrentHashMap<String, SseEmitter> tableConnections = connections.get(tableId);
-        if (tableConnections == null || tableConnections.isEmpty()) {
-            log.warn("该桌号没有SSE连接, tableId={}", tableId);
-            return;
-        }
-
-        String messageJson = JSON.toJSONString(message);
-        tableConnections.forEach((connectionId, emitter) -> {
-            try {
-                emitter.send(SseEmitter.event()
-                        .name("cart_update")
-                        .data(messageJson));
-                log.info("推送购物车更新成功, tableId={}, connectionId={}", tableId, connectionId);
-            } catch (IOException e) {
-                if (isClientDisconnect(e)) {
-                    log.debug("推送时客户端已断开, tableId={}, connectionId={}", tableId, connectionId);
-                } else {
-                    log.error("推送购物车更新失败, tableId={}, connectionId={}, error={}", tableId, connectionId, e.getMessage(), e);
-                }
-                removeConnection(tableId, connectionId);
-            }
-        });
-    }
-
-    @Override
-    public void closeConnection(Integer tableId) {
-        log.info("关闭SSE连接, tableId={}", tableId);
-        ConcurrentHashMap<String, SseEmitter> tableConnections = connections.get(tableId);
-        if (tableConnections != null) {
-            tableConnections.forEach((connectionId, emitter) -> {
-                try {
-                    emitter.complete();
-                } catch (Exception e) {
-                    log.error("关闭SSE连接失败, tableId={}, connectionId={}", tableId, connectionId, e);
-                }
-            });
-            connections.remove(tableId);
-        }
-    }
-
-    /**
-     * 判断是否为客户端主动断开(Broken pipe、Connection reset 等),此类情况属正常,无需打 ERROR。
-     */
-    private boolean isClientDisconnect(Throwable ex) {
-        if (ex == null) return false;
-        String msg = ex.getMessage();
-        if (msg != null) {
-            String lower = msg.toLowerCase();
-            if (lower.contains("broken pipe") || lower.contains("connection reset")
-                    || lower.contains("connection closed") || lower.contains("an established connection was aborted")) {
-                return true;
-            }
-        }
-        return isClientDisconnect(ex.getCause());
-    }
-
-    /**
-     * 移除连接
-     */
-    private void removeConnection(Integer tableId, String connectionId) {
-        ConcurrentHashMap<String, SseEmitter> tableConnections = connections.get(tableId);
-        if (tableConnections != null) {
-            SseEmitter emitter = tableConnections.remove(connectionId);
-            if (emitter != null) {
-                try {
-                    emitter.complete();
-                } catch (Exception e) {
-                    log.error("完成SSE连接失败, tableId={}, connectionId={}", tableId, connectionId, e);
-                }
-            }
-            if (tableConnections.isEmpty()) {
-                connections.remove(tableId);
-            }
-        }
-    }
-
-    /**
-     * 启动心跳任务
-     */
-    private void startHeartbeat(Integer tableId, String connectionId, SseEmitter emitter) {
-        scheduler.scheduleAtFixedRate(() -> {
-            try {
-                if (emitter != null) {
-                    emitter.send(SseEmitter.event()
-                            .name("heartbeat")
-                            .data("ping"));
-                }
-            } catch (IOException e) {
-                if (isClientDisconnect(e)) {
-                    log.debug("心跳时客户端已断开, tableId={}, connectionId={}", tableId, connectionId);
-                } else {
-                    log.error("发送心跳失败, tableId={}, connectionId={}", tableId, connectionId, e);
-                }
-                removeConnection(tableId, connectionId);
-            }
-        }, 30, 30, TimeUnit.SECONDS); // 每30秒发送一次心跳
-    }
-}

+ 0 - 2019
alien-store/src/main/java/shop/alien/store/service/impl/StoreOrderServiceImpl.java

@@ -1,2019 +0,0 @@
-package shop.alien.store.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.StringUtils;
-import shop.alien.store.config.BaseRedisService;
-import shop.alien.store.service.CartService;
-import shop.alien.store.service.StoreOrderService;
-import shop.alien.store.util.TokenUtil;
-import shop.alien.entity.store.*;
-import shop.alien.entity.store.dto.CartDTO;
-import shop.alien.entity.store.dto.CartItemDTO;
-import shop.alien.entity.store.dto.CreateOrderDTO;
-import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
-import shop.alien.entity.store.vo.OrderChangeLogItemVO;
-import shop.alien.entity.store.vo.OrderInfoVO;
-import shop.alien.entity.store.vo.StoreOrderPageVO;
-import shop.alien.entity.store.vo.OrderCuisineItemVO;
-import shop.alien.entity.store.vo.OrderDetailWithChangeLogVO;
-import shop.alien.mapper.*;
-
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 订单服务实现类
- *
- * @author system
- * @since 2025-01-XX
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-@Transactional(rollbackFor = Exception.class)
-public class StoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper, StoreOrder> implements StoreOrderService {
-
-
-    private final StoreOrderDetailMapper orderDetailMapper;
-    private final StoreTableMapper storeTableMapper;
-    private final StoreTableLogMapper storeTableLogMapper;
-    private final StoreCuisineMapper storeCuisineMapper;
-    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
-    private final CartService cartService;
-    private final StoreOrderLockMapper storeOrderLockMapper;
-    private final StoreCouponUsageMapper storeCouponUsageMapper;
-    private final StoreCartMapper storeCartMapper;
-    private final BaseRedisService baseRedisService;
-    private final StoreInfoMapper storeInfoMapper;
-    private final StoreOrderChangeLogMapper orderChangeLogMapper;
-    private final shop.alien.store.service.SseService sseService;
-    private final shop.alien.store.service.OrderLockService orderLockService;
-
-    @Override
-    public StoreOrder createOrder(CreateOrderDTO dto) {
-        log.info("创建订单, dto={}", dto);
-
-        // 获取当前用户信息
-        Object[] userInfo = getCurrentUserInfo();
-        Integer userId = (Integer) userInfo[0];
-        String userPhone = (String) userInfo[1];
-
-        // 检查订单锁定状态
-        Integer lockUserId = orderLockService.checkOrderLock(dto.getTableId());
-        if (lockUserId != null && !lockUserId.equals(userId)) {
-            throw new RuntimeException("订单已被其他用户锁定,无法下单");
-        }
-
-        // 验证桌号
-        StoreTable table = storeTableMapper.selectById(dto.getTableId());
-        if (table == null) {
-            throw new RuntimeException("桌号不存在");
-        }
-
-        // 查询门店信息(用于获取餐具费)
-        StoreInfo storeInfo = storeInfoMapper.selectById(table.getStoreId());
-        if (storeInfo == null) {
-            throw new RuntimeException("门店不存在");
-        }
-
-        // 获取购物车
-        CartDTO cart = cartService.getCart(dto.getTableId());
-        if (cart.getItems() == null || cart.getItems().isEmpty()) {
-            throw new RuntimeException("购物车为空");
-        }
-        
-        // 检查是否有新增商品或商品数量增加
-        boolean hasNewItems = false; // 是否有新增商品(未下单过的商品)
-        boolean hasQuantityIncrease = false; // 是否有商品数量增加
-        
-        for (shop.alien.entity.store.dto.CartItemDTO item : cart.getItems()) {
-            Integer lockedQuantity = item.getLockedQuantity();
-            Integer currentQuantity = item.getQuantity();
-            
-            if (lockedQuantity == null || lockedQuantity == 0) {
-                // 有新增商品(未下单过的商品)
-                hasNewItems = true;
-                log.debug("发现新增商品, cuisineId={}, quantity={}", item.getCuisineId(), currentQuantity);
-            } else if (currentQuantity != null && currentQuantity > lockedQuantity) {
-                // 有商品数量增加(当前数量大于已下单数量)
-                hasQuantityIncrease = true;
-                log.debug("发现商品数量增加, cuisineId={}, currentQuantity={}, orderedQuantity={}", 
-                        item.getCuisineId(), currentQuantity, lockedQuantity);
-            }
-        }
-        
-        // 如果没有新增商品且没有商品数量增加,不允许创建/更新订单(下单后只能增不能减,不支持减量同步)
-        if (!hasNewItems && !hasQuantityIncrease) {
-            throw new RuntimeException("购物车中没有新增商品或商品数量未增加,无法创建订单");
-        }
-
-        // 直接使用前端传入的值
-        BigDecimal totalAmount = dto.getTotalAmount() != null ? dto.getTotalAmount() : BigDecimal.ZERO;
-        BigDecimal tablewareFee = dto.getTablewareFee() != null ? dto.getTablewareFee() : BigDecimal.ZERO;
-        BigDecimal discountAmount = dto.getDiscountAmount() != null ? dto.getDiscountAmount() : BigDecimal.ZERO;
-        BigDecimal payAmount = dto.getPayAmount() != null ? dto.getPayAmount() : BigDecimal.ZERO;
-        
-        // 优惠券仅校验是否存在及是否属于该门店,不做金额校验;订单总金额、餐具费、优惠金额、实付金额完全采用前端传参
-        LifeDiscountCoupon coupon = null;
-        
-        if (dto.getCouponId() != null) {
-            // 检查桌号是否已使用优惠券,如果已使用则替换为新优惠券
-            if (cartService.hasUsedCoupon(dto.getTableId())) {
-                // 获取旧的优惠券使用记录
-                LambdaQueryWrapper<StoreCouponUsage> oldUsageWrapper = new LambdaQueryWrapper<>();
-                oldUsageWrapper.eq(StoreCouponUsage::getTableId, dto.getTableId());
-                oldUsageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-                oldUsageWrapper.in(StoreCouponUsage::getUsageStatus, 0, 1); // 已标记使用、已下单
-                oldUsageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-                oldUsageWrapper.last("LIMIT 1");
-                StoreCouponUsage oldUsage = storeCouponUsageMapper.selectOne(oldUsageWrapper);
-                
-                if (oldUsage != null) {
-                    // 如果旧优惠券已经关联到订单(已下单状态),需要将旧优惠券使用记录状态改为"已取消"
-                    if (oldUsage.getUsageStatus() == 1 && oldUsage.getOrderId() != null) {
-                        oldUsage.setUsageStatus(3); // 已取消
-                        oldUsage.setUpdatedTime(new Date());
-                        storeCouponUsageMapper.updateById(oldUsage);
-                        log.info("替换优惠券:取消旧优惠券使用记录, tableId={}, oldCouponId={}, newCouponId={}", 
-                                dto.getTableId(), oldUsage.getCouponId(), dto.getCouponId());
-                    } else {
-                        // 如果只是已标记使用但未下单,直接逻辑删除
-                        storeCouponUsageMapper.deleteById(oldUsage.getId());
-                        log.info("替换优惠券:删除未下单的旧优惠券使用记录, tableId={}, oldCouponId={}, newCouponId={}", 
-                                dto.getTableId(), oldUsage.getCouponId(), dto.getCouponId());
-                    }
-                }
-                
-                // 清除旧的优惠券使用标记
-                cartService.clearCouponUsed(dto.getTableId());
-                log.info("替换优惠券:清除旧优惠券标记, tableId={}, newCouponId={}", dto.getTableId(), dto.getCouponId());
-            }
-
-            // 验证优惠券(只查询一次)
-            coupon = lifeDiscountCouponMapper.selectById(dto.getCouponId());
-            if (coupon == null) {
-                throw new RuntimeException("优惠券不存在");
-            }
-
-            // 验证优惠券是否属于该门店(空安全:coupon.storeId 为 String,table.storeId 为 Integer)
-            String couponStoreId = coupon.getStoreId();
-            Integer tableStoreId = table.getStoreId();
-            if (couponStoreId == null || tableStoreId == null
-                    || !couponStoreId.equals(String.valueOf(tableStoreId))) {
-                throw new RuntimeException("优惠券不属于该门店");
-            }
-
-            // 标记桌号已使用新优惠券
-            cartService.markCouponUsed(dto.getTableId(), dto.getCouponId());
-        } else {
-            // 直接使用前端传入的值,如果为null则设为0
-            if (discountAmount == null) {
-                discountAmount = BigDecimal.ZERO;
-            }
-        }
-
-        Date now = new Date();
-        StoreOrder order = null;
-        String orderNo = null;
-        boolean isUpdate = false; // 是否是更新订单
-        
-        // 检查桌号是否已绑定订单
-        if (table.getCurrentOrderId() != null) {
-            // 查询已存在的订单
-            StoreOrder existingOrder = this.getById(table.getCurrentOrderId());
-            if (existingOrder != null && existingOrder.getOrderStatus() == 0 && existingOrder.getPayStatus() == 0) {
-                // 订单存在且是待支付状态,更新订单
-                isUpdate = true;
-                order = existingOrder;
-                orderNo = order.getOrderNo(); // 使用原订单号
-                log.info("桌号已绑定订单,更新订单信息, orderId={}, orderNo={}", order.getId(), orderNo);
-                
-                // 更新订单信息(完全采用前端传参,不做金额校验)
-                order.setDinerCount(dto.getDinerCount());
-                order.setContactPhone(dto.getContactPhone());
-                order.setTablewareFee(tablewareFee);
-                order.setTotalAmount(totalAmount);
-                order.setCouponId(dto.getCouponId());
-                order.setCurrentCouponId(dto.getCouponId());
-                order.setDiscountAmount(discountAmount);
-                order.setPayAmount(payAmount);
-                order.setRemark(dto.getRemark());
-                order.setUpdatedUserId(userId);
-                order.setUpdatedTime(now);
-                this.updateById(order);
-                
-                // 逻辑删除旧的订单明细
-                LambdaQueryWrapper<StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-                detailWrapper.eq(StoreOrderDetail::getOrderId, order.getId());
-                detailWrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-                List<StoreOrderDetail> oldDetails = orderDetailMapper.selectList(detailWrapper);
-                if (oldDetails != null && !oldDetails.isEmpty()) {
-                    List<Integer> oldDetailIds = oldDetails.stream()
-                            .map(StoreOrderDetail::getId)
-                            .collect(Collectors.toList());
-                    orderDetailMapper.deleteBatchIds(oldDetailIds);
-                    log.info("删除旧订单明细, orderId={}, count={}", order.getId(), oldDetailIds.size());
-                }
-            } else {
-                log.info("桌号绑定的订单不存在或已支付/已取消,将创建新订单");
-            }
-        }
-        
-        // 如果没有订单需要更新,创建新订单
-        if (!isUpdate) {
-            // 生成订单号
-            orderNo = generateOrderNo();
-            
-            // 创建订单
-            order = new StoreOrder();
-            order.setOrderNo(orderNo);
-            order.setStoreId(table.getStoreId());
-            order.setTableId(table.getId());
-            order.setTableNumber(table.getTableNumber());
-            order.setDinerCount(dto.getDinerCount());
-            order.setContactPhone(dto.getContactPhone());
-            order.setTablewareFee(tablewareFee);
-            order.setPayUserId(userId);
-            order.setPayUserPhone(userPhone);
-            order.setOrderStatus(0); // 待支付
-            order.setTotalAmount(totalAmount);
-            order.setCouponId(dto.getCouponId());
-            order.setCurrentCouponId(dto.getCouponId());
-            order.setDiscountAmount(discountAmount);
-            order.setPayAmount(payAmount);
-            
-            // 如果immediatePay为0,只创建订单不支付;为1则创建订单并支付
-            // 暂时不实现立即支付,由前端调用支付接口
-            // payType在支付时设置
-            order.setPayStatus(0); // 未支付
-            order.setRemark(dto.getRemark());
-            order.setCreatedUserId(userId);
-            order.setUpdatedUserId(userId);
-            // 手动设置创建时间和更新时间(临时方案,避免自动填充未生效导致 created_time 为 null)
-            order.setCreatedTime(now);
-            order.setUpdatedTime(now);
-            this.save(order);
-            log.info("创建新订单, orderId={}, orderNo={}", order.getId(), orderNo);
-        }
-        
-        // 确保 order 和 orderNo 已初始化(用于后续代码)
-        if (order == null || orderNo == null) {
-            throw new RuntimeException("订单创建失败,系统错误");
-        }
-        final StoreOrder finalOrder = order;
-        final String finalOrderNo = orderNo;
-        final boolean finalIsUpdate = isUpdate; // 用于 lambda 表达式
-
-        // 更新优惠券使用记录状态为已下单
-        if (dto.getCouponId() != null) {
-            LambdaQueryWrapper<StoreCouponUsage> usageWrapper = new LambdaQueryWrapper<>();
-            usageWrapper.eq(StoreCouponUsage::getTableId, dto.getTableId());
-            usageWrapper.eq(StoreCouponUsage::getCouponId, dto.getCouponId());
-            usageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-            usageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-            usageWrapper.last("LIMIT 1");
-            StoreCouponUsage usage = storeCouponUsageMapper.selectOne(usageWrapper);
-            if (usage != null) {
-                usage.setOrderId(finalOrder.getId());
-                usage.setUsageStatus(1); // 已下单
-                usage.setUpdatedTime(new Date());
-                storeCouponUsageMapper.updateById(usage);
-            }
-        }
-        
-        // 如果是更新订单,且优惠券发生变化,需要处理旧优惠券的使用记录
-        if (isUpdate && finalOrder.getCouponId() != null && 
-            (dto.getCouponId() == null || !finalOrder.getCouponId().equals(dto.getCouponId()))) {
-            // 订单的优惠券被替换或取消,需要将旧优惠券使用记录状态改为"已取消"
-            LambdaQueryWrapper<StoreCouponUsage> oldUsageWrapper = new LambdaQueryWrapper<>();
-            oldUsageWrapper.eq(StoreCouponUsage::getOrderId, finalOrder.getId());
-            oldUsageWrapper.eq(StoreCouponUsage::getCouponId, finalOrder.getCouponId());
-            oldUsageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-            oldUsageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-            oldUsageWrapper.last("LIMIT 1");
-            StoreCouponUsage oldUsage = storeCouponUsageMapper.selectOne(oldUsageWrapper);
-            if (oldUsage != null) {
-                oldUsage.setUsageStatus(3); // 已取消
-                oldUsage.setUpdatedTime(new Date());
-                storeCouponUsageMapper.updateById(oldUsage);
-                log.info("更新订单时替换优惠券:取消旧优惠券使用记录, orderId={}, oldCouponId={}, newCouponId={}", 
-                        finalOrder.getId(), finalOrder.getCouponId(), dto.getCouponId());
-            }
-        }
-
-        // 创建订单明细(单价、小计来自购物车)
-        // 如果是更新订单,需要判断哪些商品是新增的或数量增加的,标记为加餐
-        // 餐具的特殊ID(用于标识餐具项)
-        final Integer TABLEWARE_CUISINE_ID = -1;
-        
-        List<StoreOrderDetail> orderDetails = cart.getItems().stream()
-                .map(item -> {
-                    StoreOrderDetail detail = new StoreOrderDetail();
-                    detail.setOrderId(finalOrder.getId());
-                    detail.setOrderNo(finalOrderNo);
-                    detail.setCuisineId(item.getCuisineId());
-                    detail.setCuisineName(item.getCuisineName());
-                    
-                    // 设置菜品类型:如果为null,根据是否为餐具设置默认值
-                    Integer cuisineType = item.getCuisineType();
-                    if (cuisineType == null) {
-                        // 如果是餐具,设置为0;否则设置为1(默认单品)
-                        if (TABLEWARE_CUISINE_ID.equals(item.getCuisineId())) {
-                            cuisineType = 0; // 0表示餐具
-                        } else {
-                            // 尝试从菜品信息中获取,如果获取不到则默认为1(单品)
-                            try {
-                                StoreCuisine cuisine = storeCuisineMapper.selectById(item.getCuisineId());
-                                if (cuisine != null && cuisine.getCuisineType() != null) {
-                                    cuisineType = cuisine.getCuisineType();
-                                } else {
-                                    cuisineType = 1; // 默认为单品
-                                }
-                            } catch (Exception e) {
-                                log.warn("获取菜品类型失败, cuisineId={}, 使用默认值1", item.getCuisineId(), e);
-                                cuisineType = 1; // 默认为单品
-                            }
-                        }
-                    }
-                    detail.setCuisineType(cuisineType);
-                    
-                    detail.setCuisineImage(item.getCuisineImage());
-                    detail.setUnitPrice(item.getUnitPrice());
-                    detail.setQuantity(item.getQuantity());
-                    detail.setSubtotalAmount(item.getSubtotalAmount());
-                    detail.setAddUserId(item.getAddUserId());
-                    detail.setAddUserPhone(item.getAddUserPhone());
-                    detail.setRemark(item.getRemark());
-                    detail.setCreatedUserId(userId);
-                    detail.setCreatedTime(now);
-                    detail.setUpdatedTime(now);
-                    
-                    // 如果是更新订单,判断是否为新增商品或数量增加的商品
-                    if (finalIsUpdate) {
-                        Integer lockedQuantity = item.getLockedQuantity();
-                        // 如果是新增商品(lockedQuantity 为 null 或 0)或数量增加的商品,标记为加餐
-                        if (lockedQuantity == null || lockedQuantity == 0 || 
-                            (item.getQuantity() != null && item.getQuantity() > lockedQuantity)) {
-                            detail.setIsAddDish(1); // 标记为加餐
-                            detail.setAddDishTime(now);
-                        }
-                    }
-                    
-                    return detail;
-                })
-                .collect(Collectors.toList());
-
-        for (StoreOrderDetail detail : orderDetails) {
-            orderDetailMapper.insert(detail);
-        }
-
-        // 记录订单变更日志
-        recordOrderChangeLog(finalOrder.getId(), finalOrderNo, cart.getItems(), finalIsUpdate ? 3 : 1, now, userId, userPhone);
-
-        // 更新桌号的当前订单ID和状态(显式用 LambdaUpdateWrapper 写入,避免 updateById 忽略更新)
-        // 约定:首次下单 → 餐桌状态=就餐中(1);后续下单(更新订单/加餐) → 餐桌状态=加餐(3)
-        Integer tableId = table.getId();
-        if (!finalIsUpdate) {
-            // 首次下单:设置订单ID,餐桌状态为就餐中(1)
-            LambdaUpdateWrapper<StoreTable> newTableWrapper = new LambdaUpdateWrapper<>();
-            newTableWrapper.eq(StoreTable::getId, tableId)
-                    .set(StoreTable::getCurrentOrderId, finalOrder.getId())
-                    .set(StoreTable::getStatus, 1)
-                    .set(StoreTable::getUpdatedTime, now);
-            if (userId != null) {
-                newTableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, newTableWrapper);
-        } else {
-            // 后续下单(更新订单/加餐):餐桌状态设为加餐(3)
-            LambdaUpdateWrapper<StoreTable> addDishTableWrapper = new LambdaUpdateWrapper<>();
-            addDishTableWrapper.eq(StoreTable::getId, tableId)
-                    .set(StoreTable::getStatus, 3)
-                    .set(StoreTable::getUpdatedTime, now);
-            if (userId != null) {
-                addDishTableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, addDishTableWrapper);
-            log.info("更新订单(加餐),设置餐桌状态为加餐, tableId={}, orderId={}", tableId, finalOrder.getId());
-        }
-
-        // 锁定购物车商品数量(禁止减少或删除已下单的商品)
-        cartService.lockCartItems(dto.getTableId());
-
-        // 下单后不清空购物车,允许加餐(加餐时添加到同一订单)
-        // 只有在支付完成后才清空购物车
-
-        // 创建订单成功后,自动解锁订单锁定
-        try {
-            orderLockService.unlockOrder(dto.getTableId(), userId);
-            log.info("订单创建成功后自动解锁订单锁定, tableId={}, userId={}", dto.getTableId(), userId);
-        } catch (Exception e) {
-            log.warn("自动解锁订单锁定失败, tableId={}, userId={}, error={}", dto.getTableId(), userId, e.getMessage());
-            // 解锁失败不影响订单创建,只记录警告日志
-        }
-
-        if (isUpdate) {
-            log.info("订单更新成功, orderId={}, orderNo={}", finalOrder.getId(), finalOrderNo);
-        } else {
-            log.info("订单创建成功, orderId={}, orderNo={}", finalOrder.getId(), finalOrderNo);
-        }
-        return finalOrder;
-    }
-
-    @Override
-    public StoreOrder payOrder(Integer orderId, Integer payType) {
-        log.info("支付订单, orderId={}, payType={}", orderId, payType);
-
-        // 获取当前用户信息
-        Object[] userInfo = getCurrentUserInfo();
-        Integer userId = (Integer) userInfo[0];
-
-        // 检查结算锁定状态
-        Integer lockUserId = orderLockService.checkSettlementLock(orderId);
-        if (lockUserId != null && !lockUserId.equals(userId)) {
-            throw new RuntimeException("订单结算已被其他用户锁定,无法支付");
-        }
-
-        // 验证订单状态
-        StoreOrder order = validateOrderForOperation(orderId, 0, "支付");
-
-        // 支付时重新计算优惠券金额和实付金额(此时订单金额已确定,不会再变化)
-        BigDecimal discountAmount = BigDecimal.ZERO;
-        BigDecimal tablewareFee = order.getTablewareFee() != null ? order.getTablewareFee() : BigDecimal.ZERO;
-        BigDecimal totalAmount = order.getTotalAmount() != null ? order.getTotalAmount() : BigDecimal.ZERO;
-        BigDecimal totalWithTableware = totalAmount.add(tablewareFee);
-        
-        if (order.getCouponId() != null) {
-            // 查询优惠券信息
-            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(order.getCouponId());
-            if (coupon == null) {
-                throw new RuntimeException("优惠券不存在");
-            }
-            
-            // 验证最低消费(菜品总价 + 餐具费)
-            if (coupon.getMinimumSpendingAmount() != null
-                    && totalWithTableware.compareTo(coupon.getMinimumSpendingAmount()) < 0) {
-                throw new RuntimeException("订单金额未达到优惠券最低消费要求(" + coupon.getMinimumSpendingAmount() + "元)");
-            }
-            
-            // 计算优惠金额:根据优惠券类型(满减券或折扣券)计算
-            discountAmount = calculateDiscountAmount(coupon, totalWithTableware);
-        }
-        
-        // 计算实付金额(菜品总价 + 餐具费 - 优惠金额)
-        BigDecimal payAmount = totalWithTableware.subtract(discountAmount);
-        
-        // 更新订单信息(包括优惠金额和实付金额)
-        order.setDiscountAmount(discountAmount);
-        order.setPayAmount(payAmount);
-        order.setOrderStatus(1); // 已支付
-        order.setPayStatus(1); // 已支付
-        order.setPayType(payType);
-        order.setPayTime(new Date());
-        order.setPayTradeNo("TRADE_" + System.currentTimeMillis()); // 模拟交易号
-        order.setUpdatedTime(new Date());
-        order.setUpdatedUserId(userId);
-
-        this.updateById(order);
-
-        // 更新优惠券使用记录状态为已支付
-        if (order.getCouponId() != null) {
-            LambdaQueryWrapper<StoreCouponUsage> usageWrapper = new LambdaQueryWrapper<>();
-            usageWrapper.eq(StoreCouponUsage::getOrderId, orderId);
-            usageWrapper.eq(StoreCouponUsage::getCouponId, order.getCouponId());
-            usageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-            usageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-            usageWrapper.last("LIMIT 1");
-            StoreCouponUsage usage = storeCouponUsageMapper.selectOne(usageWrapper);
-            if (usage != null) {
-                usage.setUsageStatus(2); // 已支付
-                usage.setUpdatedTime(new Date());
-                storeCouponUsageMapper.updateById(usage);
-            }
-        }
-
-        // 支付完成后,清空购物车和重置餐桌状态(保留订单数据,不删除订单)
-        // resetTableAfterPayment 方法会清空购物车和重置餐桌状态,但不会删除订单数据
-        resetTableAfterPayment(order.getTableId());
-
-        // 支付订单成功后,自动解锁结算锁定
-        try {
-            orderLockService.unlockSettlement(orderId, userId);
-            log.info("订单支付成功后自动解锁结算锁定, orderId={}, userId={}", orderId, userId);
-        } catch (Exception e) {
-            log.warn("自动解锁结算锁定失败, orderId={}, userId={}, error={}", orderId, userId, e.getMessage());
-            // 解锁失败不影响订单支付,只记录警告日志
-        }
-
-        log.info("订单支付成功, orderId={}", orderId);
-        return order;
-    }
-
-    @Override
-    public boolean cancelOrder(Integer orderId) {
-        log.info("取消订单, orderId={}", orderId);
-
-        // 验证订单状态
-        StoreOrder order = validateOrderForOperation(orderId, 0, "取消");
-
-        order.setOrderStatus(2); // 已取消
-        order.setUpdatedTime(new Date());
-
-        // 获取当前用户信息
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            order.setUpdatedUserId(userId);
-        }
-
-        this.updateById(order);
-
-        // 恢复购物车的已下单数量(允许重新下单)
-        cartService.unlockCartItems(order.getTableId());
-
-        // 清除优惠券使用标记
-        cartService.clearCouponUsed(order.getTableId());
-
-        // 更新桌号状态:显式清空 currentOrderId(updateById 会忽略 null,必须用 LambdaUpdateWrapper)
-        Integer tableId = order.getTableId();
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            LambdaUpdateWrapper<StoreTable> tableWrapper = new LambdaUpdateWrapper<>();
-            tableWrapper.eq(StoreTable::getId, tableId)
-                    .set(StoreTable::getCurrentOrderId, null)
-                    .set(StoreTable::getUpdatedTime, new Date());
-            CartDTO cart = cartService.getCart(tableId);
-            if (cart.getItems() == null || cart.getItems().isEmpty()) {
-                tableWrapper.set(StoreTable::getStatus, 0).set(StoreTable::getDinerCount, null);
-            } else {
-                tableWrapper.set(StoreTable::getStatus, 1); // 就餐中
-            }
-            if (userId != null) {
-                tableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, tableWrapper);
-        }
-
-        log.info("订单取消成功, orderId={}", orderId);
-        return true;
-    }
-
-    @Override
-    public StoreOrder getOrderByOrderNo(String orderNo) {
-        LambdaQueryWrapper<StoreOrder> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreOrder::getOrderNo, orderNo);
-        wrapper.eq(StoreOrder::getDeleteFlag, 0);
-        return this.getOne(wrapper);
-    }
-
-    @Override
-    public StoreOrder getOrderById(Integer orderId) {
-        return this.getById(orderId);
-    }
-
-    /** 前端只传 0=进行中、3=已完成。进行中对应库表 0待支付+1已支付,已完成对应 3。 */
-    private List<Integer> resolveOrderStatusFilter(Integer orderStatus) {
-        if (orderStatus == null) {
-            return null;
-        }
-        if (orderStatus == 0) {
-            return Arrays.asList(0, 1); // 进行中 = 待支付 + 已支付
-        }
-        if (orderStatus == 3) {
-            return Collections.singletonList(3); // 已完成
-        }
-        return null; // 其他值不参与筛选
-    }
-
-    @Override
-    public IPage<StoreOrder> getOrderPage(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword) {
-        // 前端只传 0=进行中、3=已完成。进行中=待支付(0)+已支付(1),已完成=3
-        List<Integer> orderStatusList = resolveOrderStatusFilter(orderStatus);
-        LambdaQueryWrapper<StoreOrder> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreOrder::getDeleteFlag, 0);
-        if (storeId != null) {
-            wrapper.eq(StoreOrder::getStoreId, storeId);
-        }
-        if (tableId != null) {
-            wrapper.eq(StoreOrder::getTableId, tableId);
-        }
-        if (orderStatusList != null && !orderStatusList.isEmpty()) {
-            wrapper.in(StoreOrder::getOrderStatus, orderStatusList);
-        }
-        
-        // 搜索功能:按订单编号模糊搜索
-        if (StringUtils.hasText(keyword)) {
-            // 限制搜索关键词长度(15字)
-            String searchKeyword = keyword.length() > 15 ? keyword.substring(0, 15) : keyword;
-            wrapper.like(StoreOrder::getOrderNo, searchKeyword);
-        }
-        
-        wrapper.orderByDesc(StoreOrder::getCreatedTime);
-        return this.page(page, wrapper);
-    }
-
-    @Override
-    public IPage<StoreOrderPageVO> getOrderPageWithCuisines(Page<StoreOrder> page, Integer storeId, Integer tableId, Integer orderStatus, String keyword) {
-        // 前端只传 0=进行中、3=已完成。进行中=待支付(0)+已支付(1),已完成=3
-        List<Integer> orderStatusList = resolveOrderStatusFilter(orderStatus);
-        log.info("分页查询订单列表(包含菜品信息), storeId={}, tableId={}, orderStatus={}, keyword={}", storeId, tableId, orderStatusList, keyword);
-        
-        // 限制搜索关键词长度(15字)
-        String searchKeyword = null;
-        if (StringUtils.hasText(keyword)) {
-            searchKeyword = keyword.length() > 15 ? keyword.substring(0, 15) : keyword;
-        }
-        
-        // 1. 如果有关键词,需要同时支持按订单编号和菜品名称搜索
-        final Set<Integer> matchingOrderIds;
-        if (StringUtils.hasText(searchKeyword)) {
-            Set<Integer> orderIdsSet = new HashSet<>();
-            
-            // 1.1 按订单编号搜索
-            LambdaQueryWrapper<StoreOrder> orderNoWrapper = new LambdaQueryWrapper<>();
-            orderNoWrapper.eq(StoreOrder::getDeleteFlag, 0)
-                    .like(StoreOrder::getOrderNo, searchKeyword);
-            if (storeId != null) {
-                orderNoWrapper.eq(StoreOrder::getStoreId, storeId);
-            }
-            if (tableId != null) {
-                orderNoWrapper.eq(StoreOrder::getTableId, tableId);
-            }
-            if (orderStatusList != null && !orderStatusList.isEmpty()) {
-                orderNoWrapper.in(StoreOrder::getOrderStatus, orderStatusList);
-            }
-            List<StoreOrder> orderNoMatches = this.list(orderNoWrapper);
-            orderNoMatches.forEach(order -> orderIdsSet.add(order.getId()));
-            
-            // 1.2 按菜品名称搜索
-            LambdaQueryWrapper<StoreOrderDetail> detailSearchWrapper = new LambdaQueryWrapper<>();
-            detailSearchWrapper.select(StoreOrderDetail::getOrderId)
-                    .like(StoreOrderDetail::getCuisineName, searchKeyword)
-                    .eq(StoreOrderDetail::getDeleteFlag, 0);
-            
-            // 如果有限制条件,需要先查询符合条件的订单ID
-            if (storeId != null || tableId != null || (orderStatusList != null && !orderStatusList.isEmpty())) {
-                LambdaQueryWrapper<StoreOrder> filterWrapper = new LambdaQueryWrapper<>();
-                filterWrapper.eq(StoreOrder::getDeleteFlag, 0)
-                        .select(StoreOrder::getId);
-                if (storeId != null) {
-                    filterWrapper.eq(StoreOrder::getStoreId, storeId);
-                }
-                if (tableId != null) {
-                    filterWrapper.eq(StoreOrder::getTableId, tableId);
-                }
-                if (orderStatusList != null && !orderStatusList.isEmpty()) {
-                    filterWrapper.in(StoreOrder::getOrderStatus, orderStatusList);
-                }
-                List<StoreOrder> filteredOrders = this.list(filterWrapper);
-                Set<Integer> filteredOrderIds = filteredOrders.stream()
-                        .map(StoreOrder::getId)
-                        .collect(Collectors.toSet());
-                if (!filteredOrderIds.isEmpty()) {
-                    detailSearchWrapper.in(StoreOrderDetail::getOrderId, filteredOrderIds);
-                } else {
-                    // 如果没有符合条件的订单,直接返回空结果
-                    Page<StoreOrderPageVO> emptyPage = new Page<>(page.getCurrent(), page.getSize());
-                    emptyPage.setTotal(0);
-                    emptyPage.setPages(0);
-                    return emptyPage;
-                }
-            }
-            
-            List<StoreOrderDetail> matchingDetails = orderDetailMapper.selectList(detailSearchWrapper);
-            matchingDetails.forEach(detail -> orderIdsSet.add(detail.getOrderId()));
-            
-            matchingOrderIds = orderIdsSet;
-            
-            // 如果没有任何匹配的订单,返回空结果
-            if (matchingOrderIds.isEmpty()) {
-                Page<StoreOrderPageVO> emptyPage = new Page<>(page.getCurrent(), page.getSize());
-                emptyPage.setTotal(0);
-                emptyPage.setPages(0);
-                return emptyPage;
-            }
-        } else {
-            matchingOrderIds = null;
-        }
-        
-        // 2. 查询订单列表
-        LambdaQueryWrapper<StoreOrder> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreOrder::getDeleteFlag, 0);
-        if (storeId != null) {
-            wrapper.eq(StoreOrder::getStoreId, storeId);
-        }
-        if (tableId != null) {
-            wrapper.eq(StoreOrder::getTableId, tableId);
-        }
-        if (orderStatusList != null && !orderStatusList.isEmpty()) {
-            wrapper.in(StoreOrder::getOrderStatus, orderStatusList);
-        }
-        // 如果有关键词搜索,只查询匹配的订单ID
-        if (matchingOrderIds != null && !matchingOrderIds.isEmpty()) {
-            wrapper.in(StoreOrder::getId, matchingOrderIds);
-        }
-        wrapper.orderByDesc(StoreOrder::getCreatedTime);
-        
-        IPage<StoreOrder> orderPage = this.page(page, wrapper);
-        
-        // 3. 获取所有订单ID
-        List<StoreOrder> orders = orderPage.getRecords();
-        if (orders == null || orders.isEmpty()) {
-            // 如果没有订单,返回空的分页结果
-            Page<StoreOrderPageVO> resultPage = new Page<>(page.getCurrent(), page.getSize());
-            resultPage.setTotal(orderPage.getTotal());
-            resultPage.setPages(orderPage.getPages());
-            return resultPage;
-        }
-        
-        List<Integer> orderIds = orders.stream()
-                .map(StoreOrder::getId)
-                .collect(Collectors.toList());
-        
-        // 3. 批量查询所有订单的菜品详情
-        LambdaQueryWrapper<StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-        detailWrapper.in(StoreOrderDetail::getOrderId, orderIds);
-        detailWrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-        detailWrapper.orderByAsc(StoreOrderDetail::getOrderId);
-        detailWrapper.orderByAsc(StoreOrderDetail::getCreatedTime);
-        List<StoreOrderDetail> allDetails = orderDetailMapper.selectList(detailWrapper);
-        
-        // 4. 按订单ID分组菜品详情
-        Map<Integer, List<StoreOrderDetail>> detailsMap = allDetails.stream()
-                .collect(Collectors.groupingBy(StoreOrderDetail::getOrderId));
-        
-        // 4.1 批量查询菜品标签(用于分页列表展示)
-        Set<Integer> cuisineIds = allDetails.stream()
-                .map(StoreOrderDetail::getCuisineId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        Map<Integer, String> cuisineIdToTags = new HashMap<>();
-        if (!cuisineIds.isEmpty()) {
-            List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
-            if (cuisines != null) {
-                for (StoreCuisine c : cuisines) {
-                    if (c.getTags() != null) {
-                        cuisineIdToTags.put(c.getId(), c.getTags());
-                    }
-                }
-            }
-        }
-        Map<Integer, String> finalCuisineIdToTags = cuisineIdToTags;
-        
-        // 5. 批量查询门店名称
-        Set<Integer> storeIds = orders.stream().map(StoreOrder::getStoreId).filter(Objects::nonNull).collect(Collectors.toSet());
-        Map<Integer, String> storeNameMap = new HashMap<>();
-        if (!storeIds.isEmpty()) {
-            List<StoreInfo> storeList = storeInfoMapper.selectBatchIds(storeIds);
-            if (storeList != null) {
-                for (StoreInfo s : storeList) {
-                    storeNameMap.put(s.getId(), s.getStoreName());
-                }
-            }
-        }
-        
-        // 6. 构建返回结果
-        List<StoreOrderPageVO> voList = orders.stream().map(order -> {
-            StoreOrderPageVO vo = new StoreOrderPageVO();
-            vo.setOrder(order);
-            vo.setStoreName(storeNameMap.getOrDefault(order.getStoreId(), ""));
-            
-            // 获取该订单的菜品列表(含菜品标签)
-            List<StoreOrderDetail> orderDetails = detailsMap.getOrDefault(order.getId(), new ArrayList<>());
-            List<OrderCuisineItemVO> cuisineItems = orderDetails.stream()
-                    .map(detail -> {
-                        OrderCuisineItemVO item = new OrderCuisineItemVO();
-                        item.setCuisineId(detail.getCuisineId());
-                        item.setCuisineName(detail.getCuisineName());
-                        item.setCuisineImage(detail.getCuisineImage());
-                        item.setQuantity(detail.getQuantity());
-                        item.setUnitPrice(detail.getUnitPrice());
-                        item.setTags(detail.getCuisineId() != null ? finalCuisineIdToTags.get(detail.getCuisineId()) : null);
-                        return item;
-                    })
-                    .collect(Collectors.toList());
-            vo.setCuisineItems(cuisineItems);
-            
-            return vo;
-        }).collect(Collectors.toList());
-        
-        // 7. 构建分页结果
-        Page<StoreOrderPageVO> resultPage = new Page<>(page.getCurrent(), page.getSize());
-        resultPage.setRecords(voList);
-        resultPage.setTotal(orderPage.getTotal());
-        resultPage.setPages(orderPage.getPages());
-        
-        return resultPage;
-    }
-
-    @Override
-    public boolean completeOrder(Integer orderId) {
-        log.info("完成订单, orderId={}", orderId);
-
-        StoreOrder order = this.getById(orderId);
-        if (order == null) {
-            throw new RuntimeException("订单不存在");
-        }
-
-        // 检查订单状态:只有已支付状态(1)的订单才能完成
-        if (order.getOrderStatus() != 1) {
-            throw new RuntimeException("订单状态不正确,只有已支付状态的订单才能完成");
-        }
-
-        // 检查支付状态:确保订单已支付
-        if (order.getPayStatus() != 1) {
-            throw new RuntimeException("订单未支付,无法完成");
-        }
-
-        order.setOrderStatus(3); // 已完成
-        order.setUpdatedTime(new Date());
-
-        // 从 token 获取用户信息
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            order.setUpdatedUserId(userId);
-        }
-
-        this.updateById(order);
-
-        // 更新桌号状态:显式清空 currentOrderId(updateById 会忽略 null,必须用 LambdaUpdateWrapper)
-        Integer tableId = order.getTableId();
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            LambdaUpdateWrapper<StoreTable> tableWrapper = new LambdaUpdateWrapper<>();
-            tableWrapper.eq(StoreTable::getId, tableId)
-                    .set(StoreTable::getCurrentOrderId, null)
-                    .set(StoreTable::getStatus, 0)
-                    .set(StoreTable::getDinerCount, null)
-                    .set(StoreTable::getUpdatedTime, new Date());
-            if (userId != null) {
-                tableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, tableWrapper);
-        }
-
-        log.info("订单完成成功, orderId={}", orderId);
-        return true;
-    }
-
-    @Override
-    public boolean completeOrderByMerchant(Integer orderId) {
-        log.info("商家手动完成订单, orderId={}", orderId);
-
-        StoreOrder order = this.getById(orderId);
-        if (order == null) {
-            throw new RuntimeException("订单不存在");
-        }
-
-        // 商家手动完成订单,不校验支付状态,直接设置为已完成
-        order.setOrderStatus(3); // 已完成
-        order.setUpdatedTime(new Date());
-
-        // 从 token 获取用户信息
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            order.setUpdatedUserId(userId);
-        }
-
-        this.updateById(order);
-
-        // 更新桌号状态:显式清空 currentOrderId(updateById 会忽略 null,必须用 LambdaUpdateWrapper)
-        Integer tableId = order.getTableId();
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table != null) {
-            LambdaUpdateWrapper<StoreTable> tableWrapper = new LambdaUpdateWrapper<>();
-            tableWrapper.eq(StoreTable::getId, tableId)
-                    .set(StoreTable::getCurrentOrderId, null)
-                    .set(StoreTable::getStatus, 0)
-                    .set(StoreTable::getDinerCount, null)
-                    .set(StoreTable::getUpdatedTime, new Date());
-            if (userId != null) {
-                tableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, tableWrapper);
-        }
-
-        log.info("商家手动完成订单成功, orderId={}", orderId);
-        return true;
-    }
-
-    @Override
-    public StoreOrder updateOrderCoupon(Integer orderId, Integer couponId) {
-        log.info("更新订单优惠券, orderId={}, couponId={}", orderId, couponId);
-
-        // 验证订单状态
-        StoreOrder order = validateOrderForOperation(orderId, 0, "修改优惠券");
-
-        BigDecimal discountAmount = BigDecimal.ZERO;
-
-        if (couponId != null) {
-            // 验证优惠券
-            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(couponId);
-            if (coupon == null) {
-                throw new RuntimeException("优惠券不存在");
-            }
-
-            // 验证优惠券是否属于该门店
-            if (!coupon.getStoreId().equals(String.valueOf(order.getStoreId()))) {
-                throw new RuntimeException("优惠券不属于该门店");
-            }
-
-            // 验证最低消费(菜品总价 + 餐具费)
-            BigDecimal totalWithTableware = order.getTotalAmount().add(order.getTablewareFee() != null ? order.getTablewareFee() : BigDecimal.ZERO);
-            if (coupon.getMinimumSpendingAmount() != null
-                    && totalWithTableware.compareTo(coupon.getMinimumSpendingAmount()) < 0) {
-                throw new RuntimeException("订单金额未达到优惠券最低消费要求");
-            }
-
-            // 计算优惠金额:根据优惠券类型(满减券或折扣券)计算
-            discountAmount = calculateDiscountAmount(coupon, totalWithTableware);
-        }
-
-        // 如果之前有优惠券,且优惠券发生变化(包括取消优惠券),需要处理旧优惠券使用记录
-        if (order.getCouponId() != null && (couponId == null || !order.getCouponId().equals(couponId))) {
-            // 清除旧优惠券的使用标记(如果取消优惠券或更换优惠券)
-            cartService.clearCouponUsed(order.getTableId());
-            
-            LambdaQueryWrapper<StoreCouponUsage> oldUsageWrapper = new LambdaQueryWrapper<>();
-            oldUsageWrapper.eq(StoreCouponUsage::getOrderId, orderId);
-            oldUsageWrapper.eq(StoreCouponUsage::getCouponId, order.getCouponId());
-            oldUsageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-            oldUsageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-            oldUsageWrapper.last("LIMIT 1");
-            StoreCouponUsage oldUsage = storeCouponUsageMapper.selectOne(oldUsageWrapper);
-            if (oldUsage != null) {
-                oldUsage.setUsageStatus(3); // 已取消
-                oldUsage.setUpdatedTime(new Date());
-                storeCouponUsageMapper.updateById(oldUsage);
-            }
-        }
-
-        // 如果新设置了优惠券,需要标记桌号已使用优惠券,并更新或创建使用记录
-        if (couponId != null) {
-            // 检查桌号是否已使用优惠券(如果更换优惠券,之前的标记已清除)
-            if (!cartService.hasUsedCoupon(order.getTableId())) {
-                cartService.markCouponUsed(order.getTableId(), couponId);
-            }
-            LambdaQueryWrapper<StoreCouponUsage> usageWrapper = new LambdaQueryWrapper<>();
-            usageWrapper.eq(StoreCouponUsage::getTableId, order.getTableId());
-            usageWrapper.eq(StoreCouponUsage::getCouponId, couponId);
-            usageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-            usageWrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
-            usageWrapper.last("LIMIT 1");
-            StoreCouponUsage usage = storeCouponUsageMapper.selectOne(usageWrapper);
-            if (usage != null) {
-                usage.setOrderId(orderId);
-                usage.setUsageStatus(1); // 已下单
-                usage.setDiscountAmount(discountAmount);
-                usage.setUpdatedTime(new Date());
-                storeCouponUsageMapper.updateById(usage);
-            } else {
-                // 创建新的使用记录
-                StoreTable table = storeTableMapper.selectById(order.getTableId());
-                if (table != null) {
-                    Date now = new Date();
-                    StoreCouponUsage newUsage = new StoreCouponUsage();
-                    newUsage.setTableId(order.getTableId());
-                    newUsage.setStoreId(order.getStoreId());
-                    newUsage.setOrderId(orderId);
-                    newUsage.setCouponId(couponId);
-                    newUsage.setDiscountAmount(discountAmount);
-                    newUsage.setUsageStatus(1); // 已下单
-                    newUsage.setCreatedTime(now);
-                    newUsage.setUpdatedTime(now); // 设置更新时间,避免数据库约束错误
-                    Integer userId = TokenUtil.getCurrentUserId();
-                    if (userId != null) {
-                        newUsage.setCreatedUserId(userId);
-                    }
-                    storeCouponUsageMapper.insert(newUsage);
-                }
-            }
-        }
-
-        // 重新计算实付金额(菜品总价 + 餐具费 - 优惠金额)
-        BigDecimal tablewareFee = order.getTablewareFee() != null ? order.getTablewareFee() : BigDecimal.ZERO;
-        BigDecimal payAmount = order.getTotalAmount().add(tablewareFee).subtract(discountAmount);
-
-        order.setCouponId(couponId);
-        order.setCurrentCouponId(couponId);
-        order.setDiscountAmount(discountAmount);
-        order.setPayAmount(payAmount);
-        order.setUpdatedTime(new Date());
-
-        // 从 token 获取用户信息
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            order.setUpdatedUserId(userId);
-        }
-
-        this.updateById(order);
-
-        log.info("更新订单优惠券成功, orderId={}", orderId);
-        return order;
-    }
-
-    @Override
-    public boolean resetTable(Integer tableId) {
-        log.info("管理员重置餐桌, tableId={}", tableId);
-        
-        // 验证餐桌是否存在
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table == null) {
-            throw new RuntimeException("餐桌不存在");
-        }
-        
-        // 1. 删除购物车数据(逻辑删除,使用 MyBatis-Plus 的 removeBatchIds)
-        LambdaQueryWrapper<StoreCart> cartWrapper = new LambdaQueryWrapper<>();
-        cartWrapper.eq(StoreCart::getTableId, tableId);
-        cartWrapper.eq(StoreCart::getDeleteFlag, 0);
-        List<StoreCart> cartList = storeCartMapper.selectList(cartWrapper);
-        if (cartList != null && !cartList.isEmpty()) {
-            List<Integer> cartIds = cartList.stream()
-                    .map(StoreCart::getId)
-                    .collect(Collectors.toList());
-            // 使用 removeBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-            storeCartMapper.deleteBatchIds(cartIds);
-            log.info("删除购物车数据, tableId={}, count={}", tableId, cartList.size());
-        }
-        
-        // 2. 只删除未支付或已取消的订单(保留已支付/已完成的订单,避免数据丢失)
-        // 订单状态:0-待支付,1-已支付,2-已取消,3-已完成
-        LambdaQueryWrapper<StoreOrder> orderWrapper = new LambdaQueryWrapper<>();
-        orderWrapper.eq(StoreOrder::getTableId, tableId);
-        orderWrapper.eq(StoreOrder::getDeleteFlag, 0);
-        // 只查询未支付(0)或已取消(2)的订单
-        orderWrapper.in(StoreOrder::getOrderStatus, 0, 2);
-        List<StoreOrder> orderList = this.list(orderWrapper);
-        List<Integer> orderIds = new ArrayList<>();
-        if (orderList != null && !orderList.isEmpty()) {
-            orderIds = orderList.stream()
-                    .map(StoreOrder::getId)
-                    .collect(Collectors.toList());
-            
-            // 删除订单明细(逻辑删除,使用 MyBatis-Plus 的 deleteBatchIds)
-            for (Integer orderId : orderIds) {
-                LambdaQueryWrapper<StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-                detailWrapper.eq(StoreOrderDetail::getOrderId, orderId);
-                detailWrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-                List<StoreOrderDetail> detailList = orderDetailMapper.selectList(detailWrapper);
-                if (detailList != null && !detailList.isEmpty()) {
-                    List<Integer> detailIds = detailList.stream()
-                            .map(StoreOrderDetail::getId)
-                            .collect(Collectors.toList());
-                    // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-                    orderDetailMapper.deleteBatchIds(detailIds);
-                    log.info("删除订单明细, orderId={}, count={}", orderId, detailList.size());
-                }
-            }
-            
-            // 删除订单变更记录(逻辑删除,使用 MyBatis-Plus 的 deleteBatchIds)
-            for (Integer orderId : orderIds) {
-                LambdaQueryWrapper<StoreOrderChangeLog> changeLogWrapper = new LambdaQueryWrapper<>();
-                changeLogWrapper.eq(StoreOrderChangeLog::getOrderId, orderId);
-                changeLogWrapper.eq(StoreOrderChangeLog::getDeleteFlag, 0);
-                List<StoreOrderChangeLog> changeLogList = orderChangeLogMapper.selectList(changeLogWrapper);
-                if (changeLogList != null && !changeLogList.isEmpty()) {
-                    List<Integer> changeLogIds = changeLogList.stream()
-                            .map(StoreOrderChangeLog::getId)
-                            .collect(Collectors.toList());
-                    // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-                    orderChangeLogMapper.deleteBatchIds(changeLogIds);
-                    log.info("删除订单变更记录, orderId={}, count={}", orderId, changeLogList.size());
-                }
-            }
-            
-            // 删除订单(逻辑删除,使用 MyBatis-Plus 的 removeByIds)
-            // 使用 removeByIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-            this.removeByIds(orderIds);
-            log.info("删除未支付/已取消订单数据, tableId={}, count={}", tableId, orderList.size());
-        }
-        
-        // 查询该桌号的所有订单(包括已支付/已完成的),用于后续处理锁定记录
-        LambdaQueryWrapper<StoreOrder> allOrderWrapper = new LambdaQueryWrapper<>();
-        allOrderWrapper.eq(StoreOrder::getTableId, tableId);
-        allOrderWrapper.eq(StoreOrder::getDeleteFlag, 0);
-        List<StoreOrder> allOrderList = this.list(allOrderWrapper);
-        List<Integer> allOrderIds = new ArrayList<>();
-        if (allOrderList != null && !allOrderList.isEmpty()) {
-            allOrderIds = allOrderList.stream()
-                    .map(StoreOrder::getId)
-                    .collect(Collectors.toList());
-        }
-        
-        // 3. 只删除未下单的优惠券使用记录(保留已下单/已支付的记录,避免数据丢失)
-        // usageStatus: 0-已标记使用, 1-已下单, 2-已支付, 3-已取消
-        LambdaQueryWrapper<StoreCouponUsage> couponUsageWrapper = new LambdaQueryWrapper<>();
-        couponUsageWrapper.eq(StoreCouponUsage::getTableId, tableId);
-        couponUsageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-        // 只删除已标记使用但未下单的记录(usageStatus=0)
-        couponUsageWrapper.eq(StoreCouponUsage::getUsageStatus, 0);
-        List<StoreCouponUsage> couponUsageList = storeCouponUsageMapper.selectList(couponUsageWrapper);
-        if (couponUsageList != null && !couponUsageList.isEmpty()) {
-            List<Integer> couponUsageIds = couponUsageList.stream()
-                    .map(StoreCouponUsage::getId)
-                    .collect(Collectors.toList());
-            // 使用 deleteBatchIds 进行逻辑删除(MyBatis-Plus 会自动处理 @TableLogic)
-            storeCouponUsageMapper.deleteBatchIds(couponUsageIds);
-            log.info("删除未下单的优惠券使用记录, tableId={}, count={}", tableId, couponUsageList.size());
-        }
-        
-        // 4. 删除该桌号的所有订单锁定记录(逻辑删除)
-        // 包括下单锁定(lock_type=1,通过 tableId 查找)和结算锁定(lock_type=2,通过订单ID关联)
-        
-        // 删除下单锁定(通过 tableId 查找)
-        LambdaQueryWrapper<StoreOrderLock> tableLockWrapper = new LambdaQueryWrapper<>();
-        tableLockWrapper.eq(StoreOrderLock::getTableId, tableId);
-        tableLockWrapper.eq(StoreOrderLock::getDeleteFlag, 0);
-        List<StoreOrderLock> tableLockList = storeOrderLockMapper.selectList(tableLockWrapper);
-        if (tableLockList != null && !tableLockList.isEmpty()) {
-            List<Integer> tableLockIds = tableLockList.stream()
-                    .map(StoreOrderLock::getId)
-                    .collect(Collectors.toList());
-            storeOrderLockMapper.deleteBatchIds(tableLockIds);
-            log.info("删除下单锁定记录, tableId={}, count={}", tableId, tableLockList.size());
-        }
-        
-        // 删除结算锁定(通过 orderId 查找,如果有订单的话)
-        // 注意:这里使用 allOrderIds,包括所有订单(已删除和未删除的),因为锁定记录可能关联已支付的订单
-        if (!allOrderIds.isEmpty()) {
-            LambdaQueryWrapper<StoreOrderLock> orderLockWrapper = new LambdaQueryWrapper<>();
-            orderLockWrapper.in(StoreOrderLock::getOrderId, allOrderIds);
-            orderLockWrapper.eq(StoreOrderLock::getDeleteFlag, 0);
-            List<StoreOrderLock> orderLockList = storeOrderLockMapper.selectList(orderLockWrapper);
-            if (orderLockList != null && !orderLockList.isEmpty()) {
-                List<Integer> orderLockIds = orderLockList.stream()
-                        .map(StoreOrderLock::getId)
-                        .collect(Collectors.toList());
-                storeOrderLockMapper.deleteBatchIds(orderLockIds);
-                log.info("删除结算锁定记录, orderIds={}, count={}", allOrderIds, orderLockList.size());
-            }
-        }
-        
-        // 5. 清空Redis中的购物车缓存
-        String cartKey = "cart:table:" + tableId;
-        baseRedisService.delete(cartKey);
-        log.info("清空Redis购物车缓存, tableId={}", tableId);
-        
-        // 6. 清除优惠券使用标记(Redis中的标记)
-        cartService.clearCouponUsed(tableId);
-        log.info("清除优惠券使用标记, tableId={}", tableId);
-        
-        // 7. 重置餐桌表(使用 LambdaUpdateWrapper 来显式设置 null 值)
-        LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(StoreTable::getId, tableId)
-                .set(StoreTable::getCurrentOrderId, null)  // 显式设置 null
-                .set(StoreTable::getCurrentCouponId, null)  // 显式设置 null
-                .set(StoreTable::getCartItemCount, 0)
-                .set(StoreTable::getCartTotalAmount, BigDecimal.ZERO)
-                .set(StoreTable::getStatus, 0)  // 空闲
-                .set(StoreTable::getDinerCount, null)  // 清空就餐人数
-                .set(StoreTable::getUpdatedTime, new Date());
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            updateWrapper.set(StoreTable::getUpdatedUserId, userId);
-        }
-        storeTableMapper.update(null, updateWrapper);
-        log.info("重置餐桌表完成, tableId={}", tableId);
-        
-        return true;
-    }
-
-    /**
-     * 支付完成后重置餐桌(保留订单数据,只重置餐桌绑定关系)
-     *
-     * @param tableId 餐桌ID
-     */
-    @Override
-    public void resetTableAfterPayment(Integer tableId) {
-        log.info("支付完成后重置餐桌, tableId={}", tableId);
-
-        // 验证餐桌是否存在
-        StoreTable table = storeTableMapper.selectById(tableId);
-        if (table == null) {
-            log.warn("餐桌不存在,跳过重置, tableId={}", tableId);
-            return;
-        }
-
-        // 1. 完全清空购物车(包括已下单的商品,因为订单已支付完成)
-        // 逻辑删除所有购物车数据
-        LambdaQueryWrapper<StoreCart> cartWrapper = new LambdaQueryWrapper<>();
-        cartWrapper.eq(StoreCart::getTableId, tableId);
-        cartWrapper.eq(StoreCart::getDeleteFlag, 0);
-        List<StoreCart> cartList = storeCartMapper.selectList(cartWrapper);
-        if (cartList != null && !cartList.isEmpty()) {
-            List<Integer> cartIds = cartList.stream()
-                    .map(StoreCart::getId)
-                    .collect(Collectors.toList());
-            storeCartMapper.deleteBatchIds(cartIds);
-            log.info("支付完成后删除购物车数据, tableId={}, count={}", tableId, cartList.size());
-        }
-
-        // 2. 清空Redis中的购物车缓存
-        String cartKey = "cart:table:" + tableId;
-        baseRedisService.delete(cartKey);
-        log.info("清空Redis购物车缓存, tableId={}", tableId);
-
-        // 3. 清除优惠券使用标记
-        cartService.clearCouponUsed(tableId);
-        log.info("清除优惠券使用标记, tableId={}", tableId);
-
-        // 4. 重置餐桌表(使用 LambdaUpdateWrapper 来显式设置 null 值)
-        LambdaUpdateWrapper<StoreTable> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(StoreTable::getId, tableId)
-                .set(StoreTable::getCurrentOrderId, null)  // 显式设置 null
-                .set(StoreTable::getCurrentCouponId, null)  // 显式设置 null
-                .set(StoreTable::getCartItemCount, 0)
-                .set(StoreTable::getCartTotalAmount, BigDecimal.ZERO)
-                .set(StoreTable::getStatus, 0)  // 空闲
-                .set(StoreTable::getDinerCount, null)  // 清空就餐人数
-                .set(StoreTable::getUpdatedTime, new Date());
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId != null) {
-            updateWrapper.set(StoreTable::getUpdatedUserId, userId);
-        }
-        storeTableMapper.update(null, updateWrapper);
-        log.info("支付完成后重置餐桌表完成, tableId={}", tableId);
-    }
-
-    @Override
-    public IPage<StoreOrder> getMyOrders(Page<StoreOrder> page, String type) {
-        log.info("查询我的订单, type={}", type);
-
-        // 获取当前用户ID
-        Integer userId = TokenUtil.getCurrentUserId();
-        if (userId == null) {
-            throw new RuntimeException("用户未登录");
-        }
-
-        LambdaQueryWrapper<StoreOrder> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreOrder::getDeleteFlag, 0);
-        wrapper.eq(StoreOrder::getCreatedUserId, userId); // 查询当前用户创建的订单
-
-        // 根据类型过滤订单
-        if ("0".equals(type) || "unpaid".equalsIgnoreCase(type)) {
-            // 未支付订单:orderStatus=0 且 payStatus=0
-            wrapper.eq(StoreOrder::getOrderStatus, 0);
-            wrapper.eq(StoreOrder::getPayStatus, 0);
-            log.info("查询未支付订单, userId={}", userId);
-        } else if ("1".equals(type) || "history".equalsIgnoreCase(type)) {
-            // 历史订单:已支付或已完成的订单(orderStatus=1 或 3,payStatus=1)
-            wrapper.and(w -> w.and(w1 -> w1.eq(StoreOrder::getOrderStatus, 1).eq(StoreOrder::getPayStatus, 1))
-                    .or(w2 -> w2.eq(StoreOrder::getOrderStatus, 3).eq(StoreOrder::getPayStatus, 1)));
-            log.info("查询历史订单, userId={}", userId);
-        } else {
-            // 如果类型不明确,返回所有订单
-            log.warn("订单类型不明确, type={}, 返回所有订单", type);
-        }
-
-        wrapper.orderByDesc(StoreOrder::getCreatedTime);
-        return this.page(page, wrapper);
-    }
-
-    @Override
-    public IPage<StoreOrderPageVO> getMyOrdersWithCuisines(Page<StoreOrder> page, String type) {
-        log.info("查询我的订单(包含菜品信息), type={}", type);
-
-        // 1. 查询订单列表
-        IPage<StoreOrder> orderPage = getMyOrders(page, type);
-
-        // 2. 获取所有订单ID
-        List<StoreOrder> orders = orderPage.getRecords();
-        if (orders == null || orders.isEmpty()) {
-            // 如果没有订单,返回空的分页结果
-            Page<StoreOrderPageVO> resultPage = new Page<>(page.getCurrent(), page.getSize());
-            resultPage.setTotal(orderPage.getTotal());
-            resultPage.setPages(orderPage.getPages());
-            return resultPage;
-        }
-
-        List<Integer> orderIds = orders.stream()
-                .map(StoreOrder::getId)
-                .collect(Collectors.toList());
-
-        // 3. 批量查询所有订单的菜品详情
-        LambdaQueryWrapper<StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-        detailWrapper.in(StoreOrderDetail::getOrderId, orderIds);
-        detailWrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-        detailWrapper.orderByAsc(StoreOrderDetail::getOrderId);
-        detailWrapper.orderByAsc(StoreOrderDetail::getCreatedTime);
-        List<StoreOrderDetail> allDetails = orderDetailMapper.selectList(detailWrapper);
-
-        // 4. 按订单ID分组菜品详情
-        Map<Integer, List<StoreOrderDetail>> detailsMap = allDetails.stream()
-                .collect(Collectors.groupingBy(StoreOrderDetail::getOrderId));
-
-        // 4.1 批量查询菜品标签(用于我的订单分页展示)
-        Set<Integer> cuisineIdsMy = allDetails.stream()
-                .map(StoreOrderDetail::getCuisineId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        Map<Integer, String> cuisineIdToTagsMy = new HashMap<>();
-        if (!cuisineIdsMy.isEmpty()) {
-            List<StoreCuisine> cuisinesMy = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIdsMy));
-            if (cuisinesMy != null) {
-                for (StoreCuisine c : cuisinesMy) {
-                    if (c.getTags() != null) {
-                        cuisineIdToTagsMy.put(c.getId(), c.getTags());
-                    }
-                }
-            }
-        }
-        Map<Integer, String> finalCuisineIdToTagsMy = cuisineIdToTagsMy;
-
-        // 5. 批量查询门店名称
-        Set<Integer> storeIds = orders.stream().map(StoreOrder::getStoreId).filter(Objects::nonNull).collect(Collectors.toSet());
-        Map<Integer, String> storeNameMap = new HashMap<>();
-        if (!storeIds.isEmpty()) {
-            List<StoreInfo> storeList = storeInfoMapper.selectBatchIds(storeIds);
-            if (storeList != null) {
-                for (StoreInfo s : storeList) {
-                    storeNameMap.put(s.getId(), s.getStoreName());
-                }
-            }
-        }
-
-        // 6. 构建返回结果
-        List<StoreOrderPageVO> voList = orders.stream().map(order -> {
-            StoreOrderPageVO vo = new StoreOrderPageVO();
-            vo.setOrder(order);
-            vo.setStoreName(storeNameMap.getOrDefault(order.getStoreId(), ""));
-
-            // 获取该订单的菜品列表(含菜品标签)
-            List<StoreOrderDetail> orderDetails = detailsMap.getOrDefault(order.getId(), new ArrayList<>());
-            List<OrderCuisineItemVO> cuisineItems = orderDetails.stream()
-                    .map(detail -> {
-                        OrderCuisineItemVO item = new OrderCuisineItemVO();
-                        item.setCuisineId(detail.getCuisineId());
-                        item.setCuisineName(detail.getCuisineName());
-                        item.setCuisineImage(detail.getCuisineImage());
-                        item.setQuantity(detail.getQuantity());
-                        item.setUnitPrice(detail.getUnitPrice());
-                        item.setTags(detail.getCuisineId() != null ? finalCuisineIdToTagsMy.get(detail.getCuisineId()) : null);
-                        return item;
-                    })
-                    .collect(Collectors.toList());
-            vo.setCuisineItems(cuisineItems);
-
-            return vo;
-        }).collect(Collectors.toList());
-
-        // 7. 构建分页结果
-        Page<StoreOrderPageVO> resultPage = new Page<>(page.getCurrent(), page.getSize());
-        resultPage.setRecords(voList);
-        resultPage.setTotal(orderPage.getTotal());
-        resultPage.setPages(orderPage.getPages());
-
-        return resultPage;
-    }
-
-    @Override
-    public OrderInfoVO getOrderInfo(Integer orderId) {
-        log.info("查询订单信息, orderId={}", orderId);
-        
-        // 1. 查询订单基本信息
-        StoreOrder order = this.getById(orderId);
-        if (order == null || order.getDeleteFlag() == 1) {
-            throw new RuntimeException("订单不存在");
-        }
-        
-        // 2. 查询订单明细(菜品清单)
-        LambdaQueryWrapper<StoreOrderDetail> detailWrapper = new LambdaQueryWrapper<>();
-        detailWrapper.eq(StoreOrderDetail::getOrderId, orderId);
-        detailWrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
-        detailWrapper.orderByDesc(StoreOrderDetail::getCreatedTime);
-        List<StoreOrderDetail> details = orderDetailMapper.selectList(detailWrapper);
-        
-        // 批量查询菜品标签(订单明细无 tags,从价目表取)
-        java.util.Set<Integer> cuisineIds = details.stream()
-                .map(StoreOrderDetail::getCuisineId)
-                .filter(java.util.Objects::nonNull)
-                .collect(Collectors.toSet());
-        java.util.Map<Integer, String> cuisineIdToTags = new java.util.HashMap<>();
-        if (!cuisineIds.isEmpty()) {
-            List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(cuisineIds);
-            if (cuisines != null) {
-                for (StoreCuisine c : cuisines) {
-                    cuisineIdToTags.put(c.getId(), c.getTags());
-                }
-            }
-        }
-        final java.util.Map<Integer, String> tagsMap = cuisineIdToTags;
-        
-        // 转换为CartItemDTO(含 tags)
-        List<CartItemDTO> items = details.stream().map(detail -> {
-            CartItemDTO item = new CartItemDTO();
-            item.setCuisineId(detail.getCuisineId());
-            item.setCuisineName(detail.getCuisineName());
-            item.setCuisineType(detail.getCuisineType());
-            item.setCuisineImage(detail.getCuisineImage());
-            item.setUnitPrice(detail.getUnitPrice());
-            item.setQuantity(detail.getQuantity());
-            item.setSubtotalAmount(detail.getSubtotalAmount());
-            item.setAddUserId(detail.getAddUserId());
-            item.setAddUserPhone(detail.getAddUserPhone());
-            item.setRemark(detail.getRemark());
-            item.setTags(detail.getCuisineId() != null ? tagsMap.get(detail.getCuisineId()) : null);
-            return item;
-        }).collect(Collectors.toList());
-        
-        // 3. 查询门店信息
-        StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
-        String storeName = "";
-        String storeTel = "";
-        String storeAddress = "";
-        String storeBlurb = "";
-        String storeType = "";
-        Integer businessStatus = null;
-        if (storeInfo != null) {
-            storeName = storeInfo.getStoreName();
-            storeTel = storeInfo.getStoreTel();
-            storeAddress = storeInfo.getStoreAddress();
-            storeBlurb = storeInfo.getStoreBlurb();
-            storeType = storeInfo.getStoreType();
-            businessStatus = storeInfo.getBusinessStatus();
-        }
-
-        // 4. 查询优惠券信息(如果有)
-        String couponName = null;
-        Integer couponType = null;
-        BigDecimal discountRate = null;
-        BigDecimal nominalValue = null;
-        BigDecimal minimumSpendingAmount = null;
-        if (order.getCouponId() != null) {
-            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(order.getCouponId());
-            if (coupon != null) {
-                couponName = coupon.getName();
-                couponType = coupon.getCouponType();
-                discountRate = coupon.getDiscountRate();
-                nominalValue = coupon.getNominalValue();
-                minimumSpendingAmount = coupon.getMinimumSpendingAmount();
-            }
-        }
-
-        // 5. 组装OrderInfoVO
-        OrderInfoVO vo = new OrderInfoVO();
-        vo.setOrderId(order.getId());
-        vo.setOrderNo(order.getOrderNo());
-        vo.setStoreId(order.getStoreId());
-        vo.setStoreName(storeName);
-        vo.setStoreTel(storeTel);
-        vo.setStoreAddress(storeAddress);
-        vo.setStoreBlurb(storeBlurb);
-        vo.setStoreType(storeType);
-        vo.setBusinessStatus(businessStatus);
-        vo.setTableNumber(order.getTableNumber());
-        vo.setDinerCount(order.getDinerCount());
-        vo.setContactPhone(order.getContactPhone());
-        vo.setRemark(order.getRemark());
-        vo.setItems(items);
-        vo.setTotalAmount(order.getTotalAmount());
-        vo.setTablewareFee(order.getTablewareFee());
-        vo.setCouponId(order.getCouponId());
-        vo.setCouponName(couponName);
-        vo.setCouponType(couponType);
-        vo.setDiscountRate(discountRate);
-        vo.setNominalValue(nominalValue);
-        vo.setMinimumSpendingAmount(minimumSpendingAmount);
-        vo.setDiscountAmount(order.getDiscountAmount());
-        vo.setPayAmount(order.getPayAmount());
-        vo.setOrderStatus(order.getOrderStatus());
-        vo.setPayStatus(order.getPayStatus());
-        vo.setPayType(order.getPayType());
-        vo.setCreatedTime(order.getCreatedTime());
-        vo.setPayTime(order.getPayTime());
-        
-        log.info("查询订单信息完成, orderId={}, itemCount={}", orderId, items.size());
-        return vo;
-    }
-
-    @Override
-    public List<OrderChangeLogBatchVO> getOrderChangeLogs(Integer orderId) {
-        log.info("查询订单变更记录, orderId={}", orderId);
-        
-        // 1. 查询订单的所有变更记录
-        LambdaQueryWrapper<StoreOrderChangeLog> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(StoreOrderChangeLog::getOrderId, orderId);
-        wrapper.eq(StoreOrderChangeLog::getDeleteFlag, 0);
-        wrapper.orderByAsc(StoreOrderChangeLog::getOperationTime);
-        wrapper.orderByAsc(StoreOrderChangeLog::getBatchNo);
-        List<StoreOrderChangeLog> logs = orderChangeLogMapper.selectList(wrapper);
-        
-        if (logs == null || logs.isEmpty()) {
-            log.info("订单没有变更记录, orderId={}", orderId);
-            return new ArrayList<>();
-        }
-        
-        // 2. 按批次号分组
-        Map<String, List<StoreOrderChangeLog>> batchMap = logs.stream()
-                .collect(Collectors.groupingBy(StoreOrderChangeLog::getBatchNo));
-        
-        // 2.1 批量查询菜品标签(用于订单详情展示)
-        Set<Integer> cuisineIds = logs.stream()
-                .map(StoreOrderChangeLog::getCuisineId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        Map<Integer, String> cuisineIdToTags = new HashMap<>();
-        if (!cuisineIds.isEmpty()) {
-            List<StoreCuisine> cuisines = storeCuisineMapper.selectBatchIds(new ArrayList<>(cuisineIds));
-            if (cuisines != null) {
-                for (StoreCuisine c : cuisines) {
-                    if (c.getTags() != null) {
-                        cuisineIdToTags.put(c.getId(), c.getTags());
-                    }
-                }
-            }
-        }
-        
-        // 3. 转换为批次VO列表
-        List<OrderChangeLogBatchVO> batchList = new ArrayList<>();
-        for (Map.Entry<String, List<StoreOrderChangeLog>> entry : batchMap.entrySet()) {
-            String batchNo = entry.getKey();
-            List<StoreOrderChangeLog> batchLogs = entry.getValue();
-            
-            if (batchLogs.isEmpty()) {
-                continue;
-            }
-            
-            // 取第一条记录作为批次信息(同一批次的操作类型、时间等信息相同)
-            StoreOrderChangeLog firstLog = batchLogs.get(0);
-            
-            OrderChangeLogBatchVO batchVO = new OrderChangeLogBatchVO();
-            batchVO.setBatchNo(batchNo);
-            batchVO.setOperationType(firstLog.getOperationType());
-            batchVO.setOperationTypeText(getOperationTypeText(firstLog.getOperationType()));
-            batchVO.setOperationTime(firstLog.getOperationTime());
-            batchVO.setOperatorUserId(firstLog.getOperatorUserId());
-            batchVO.setOperatorUserPhone(firstLog.getOperatorUserPhone());
-            batchVO.setRemark(firstLog.getRemark());
-            
-            // 计算批次统计信息
-            Integer totalQuantityChange = batchLogs.stream()
-                    .mapToInt(log -> log.getQuantityChange() != null ? log.getQuantityChange() : 0)
-                    .sum();
-            BigDecimal totalAmountChange = batchLogs.stream()
-                    .map(log -> log.getAmountChange() != null ? log.getAmountChange() : BigDecimal.ZERO)
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
-            
-            batchVO.setTotalQuantityChange(totalQuantityChange);
-            batchVO.setTotalAmountChange(totalAmountChange);
-            batchVO.setItemCount(batchLogs.size());
-            
-            // 转换为商品项VO列表(含菜品标签)
-            Map<Integer, String> finalCuisineIdToTags = cuisineIdToTags;
-            List<OrderChangeLogItemVO> items = batchLogs.stream().map(log -> {
-                OrderChangeLogItemVO itemVO = new OrderChangeLogItemVO();
-                itemVO.setCuisineId(log.getCuisineId());
-                itemVO.setCuisineName(log.getCuisineName());
-                itemVO.setCuisineType(log.getCuisineType());
-                itemVO.setCuisineImage(log.getCuisineImage());
-                itemVO.setUnitPrice(log.getUnitPrice());
-                itemVO.setQuantityChange(log.getQuantityChange());
-                itemVO.setQuantityBefore(log.getQuantityBefore());
-                itemVO.setQuantityAfter(log.getQuantityAfter());
-                itemVO.setAmountChange(log.getAmountChange());
-                itemVO.setRemark(log.getRemark());
-                itemVO.setTags(log.getCuisineId() != null ? finalCuisineIdToTags.get(log.getCuisineId()) : null);
-                return itemVO;
-            }).collect(Collectors.toList());
-            
-            batchVO.setItems(items);
-            batchList.add(batchVO);
-        }
-        
-        log.info("查询订单变更记录完成, orderId={}, batchCount={}", orderId, batchList.size());
-        return batchList;
-    }
-
-    @Override
-    public OrderDetailWithChangeLogVO getOrderDetailWithChangeLog(Integer orderId) {
-        log.info("查询订单详情(包含变更记录), orderId={}", orderId);
-
-        // 1. 查询订单基本信息
-        StoreOrder order = this.getById(orderId);
-        if (order == null || order.getDeleteFlag() == 1) {
-            throw new RuntimeException("订单不存在");
-        }
-
-        // 2. 查询门店信息
-        StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
-        String storeName = storeInfo != null ? storeInfo.getStoreName() : "";
-
-        // 3. 查询优惠券信息(如果有)
-        String couponName = null;
-        if (order.getCouponId() != null) {
-            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(order.getCouponId());
-            if (coupon != null) {
-                couponName = coupon.getName();
-            }
-        }
-
-        // 4. 查询订单变更记录(按批次分组)
-        List<OrderChangeLogBatchVO> changeLogBatches = getOrderChangeLogs(orderId);
-
-        // 5. 组装OrderDetailWithChangeLogVO
-        OrderDetailWithChangeLogVO vo = new OrderDetailWithChangeLogVO();
-        vo.setOrderId(order.getId());
-        vo.setOrderNo(order.getOrderNo());
-        vo.setStoreName(storeName);
-        vo.setTableNumber(order.getTableNumber());
-        vo.setDinerCount(order.getDinerCount());
-        vo.setContactPhone(order.getContactPhone());
-        vo.setRemark(order.getRemark());
-        vo.setTotalAmount(order.getTotalAmount());
-        vo.setTablewareFee(order.getTablewareFee());
-        vo.setCouponId(order.getCouponId());
-        vo.setCouponName(couponName);
-        vo.setDiscountAmount(order.getDiscountAmount());
-        vo.setPayAmount(order.getPayAmount());
-        vo.setOrderStatus(order.getOrderStatus());
-        vo.setPayStatus(order.getPayStatus());
-        vo.setPayType(order.getPayType());
-        vo.setCreatedTime(order.getCreatedTime());
-        vo.setPayTime(order.getPayTime());
-        vo.setChangeLogBatches(changeLogBatches);
-
-        log.info("查询订单详情(包含变更记录)完成, orderId={}, batchCount={}", orderId, changeLogBatches.size());
-        return vo;
-    }
-    
-    /**
-     * 获取操作类型文本
-     */
-    private String getOperationTypeText(Integer operationType) {
-        if (operationType == null) {
-            return "未知";
-        }
-        switch (operationType) {
-            case 1:
-                return "首次下单";
-            case 3:
-                return "更新订单";
-            default:
-                return "未知";
-        }
-    }
-
-    /**
-     * 记录订单变更日志
-     *
-     * @param orderId 订单ID
-     * @param orderNo 订单号
-     * @param items 商品列表
-     * @param operationType 操作类型(1:首次下单, 3:更新订单)
-     * @param operationTime 操作时间
-     * @param userId 操作人ID
-     * @param userPhone 操作人手机号
-     */
-    private void recordOrderChangeLog(Integer orderId, String orderNo, List<shop.alien.entity.store.dto.CartItemDTO> items,
-                                      Integer operationType, Date operationTime, Integer userId, String userPhone) {
-        if (items == null || items.isEmpty()) {
-            log.warn("商品列表为空,不记录变更日志, orderId={}", orderId);
-            return;
-        }
-
-        // 生成批次号:ORDER{orderId}_{yyyyMMddHHmmss}
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
-        String timestamp = sdf.format(operationTime);
-        String batchNo = "ORDER" + orderId + "_" + timestamp;
-
-        List<StoreOrderChangeLog> changeLogs = new ArrayList<>();
-
-        for (shop.alien.entity.store.dto.CartItemDTO item : items) {
-            Integer lockedQuantity = item.getLockedQuantity(); // 已下单数量
-            Integer currentQuantity = item.getQuantity(); // 当前数量
-            Integer quantityChange = 0; // 数量变化
-            Integer quantityBefore = 0; // 变化前数量
-            Integer quantityAfter = 0; // 变化后数量
-
-            if (operationType == 1) {
-                // 首次下单:记录所有商品
-                quantityBefore = 0;
-                quantityAfter = currentQuantity != null ? currentQuantity : 0;
-                quantityChange = quantityAfter;
-            } else if (operationType == 3) {
-                // 更新订单:只记录新增的商品或数量增加的商品
-                if (lockedQuantity == null || lockedQuantity == 0) {
-                    // 新增商品
-                    quantityBefore = 0;
-                    quantityAfter = currentQuantity != null ? currentQuantity : 0;
-                    quantityChange = quantityAfter;
-                } else if (currentQuantity != null && currentQuantity > lockedQuantity) {
-                    // 数量增加
-                    quantityBefore = lockedQuantity;
-                    quantityAfter = currentQuantity;
-                    quantityChange = quantityAfter - quantityBefore;
-                } else {
-                    // 没有变化,跳过
-                    continue;
-                }
-            }
-
-            // 只记录有数量变化的商品
-            if (quantityChange == null || quantityChange == 0) {
-                continue;
-            }
-
-            // 计算金额变化
-            BigDecimal amountChange = item.getUnitPrice() != null
-                    ? item.getUnitPrice().multiply(BigDecimal.valueOf(quantityChange))
-                    : BigDecimal.ZERO;
-
-            StoreOrderChangeLog changeLog = new StoreOrderChangeLog();
-            changeLog.setOrderId(orderId);
-            changeLog.setOrderNo(orderNo);
-            changeLog.setBatchNo(batchNo);
-            changeLog.setOperationType(operationType);
-            changeLog.setCuisineId(item.getCuisineId());
-            changeLog.setCuisineName(item.getCuisineName());
-            changeLog.setCuisineType(item.getCuisineType());
-            changeLog.setCuisineImage(item.getCuisineImage());
-            changeLog.setUnitPrice(item.getUnitPrice());
-            changeLog.setQuantityChange(quantityChange);
-            changeLog.setQuantityBefore(quantityBefore);
-            changeLog.setQuantityAfter(quantityAfter);
-            changeLog.setAmountChange(amountChange);
-            changeLog.setOperationTime(operationTime);
-            changeLog.setOperatorUserId(userId);
-            changeLog.setOperatorUserPhone(userPhone);
-            changeLog.setRemark(item.getRemark());
-            changeLog.setCreatedUserId(userId);
-            changeLog.setCreatedTime(operationTime);
-            changeLog.setUpdatedTime(operationTime);
-
-            changeLogs.add(changeLog);
-        }
-
-        // 批量插入变更记录(使用 MyBatis-Plus 的批量插入)
-        if (!changeLogs.isEmpty()) {
-            // 使用循环插入(MyBatis-Plus 的 BaseMapper 没有批量插入方法,需要手动实现或使用 ServiceImpl 的 saveBatch)
-            // 注意:如果变更记录数量很大,可以考虑使用 MyBatis 的批量插入
-            for (StoreOrderChangeLog log : changeLogs) {
-                orderChangeLogMapper.insert(log);
-            }
-            log.info("记录订单变更日志完成, orderId={}, batchNo={}, operationType={}, itemCount={}",
-                    orderId, batchNo, operationType, changeLogs.size());
-        } else {
-            log.warn("没有需要记录的变更, orderId={}, operationType={}", orderId, operationType);
-        }
-    }
-
-    /**
-     * 生成订单号
-     */
-    private String generateOrderNo() {
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
-        String timestamp = sdf.format(new Date());
-        String random = String.valueOf((int) (Math.random() * 10000));
-        return "ORD" + timestamp + String.format("%04d", Integer.parseInt(random));
-    }
-
-
-    @Override
-    public void migrateTableData(Integer fromTableId, Integer toTableId, Integer userId) {
-        log.info("换桌迁移数据, fromTableId={}, toTableId={}, userId={}", fromTableId, toTableId, userId);
-
-        // 1. 查询原桌号信息
-        StoreTable fromTable = storeTableMapper.selectById(fromTableId);
-        if (fromTable == null) {
-            throw new RuntimeException("原桌号不存在");
-        }
-
-        // 2. 查询目标桌号信息
-        StoreTable toTable = storeTableMapper.selectById(toTableId);
-        if (toTable == null) {
-            throw new RuntimeException("目标桌号不存在");
-        }
-
-        // 3. 迁移未完成的订单(orderStatus=0 且 payStatus=0)
-        if (fromTable.getCurrentOrderId() != null) {
-            StoreOrder pendingOrder = this.getById(fromTable.getCurrentOrderId());
-            if (pendingOrder != null && pendingOrder.getOrderStatus() == 0 && pendingOrder.getPayStatus() == 0) {
-                // 更新订单的桌号信息
-                pendingOrder.setTableId(toTableId);
-                pendingOrder.setTableNumber(toTable.getTableNumber());
-                pendingOrder.setUpdatedUserId(userId);
-                pendingOrder.setUpdatedTime(new Date());
-                this.updateById(pendingOrder);
-                log.info("迁移未完成订单, orderId={}, fromTableId={}, toTableId={}", pendingOrder.getId(), fromTableId, toTableId);
-
-                // 更新订单明细的订单号(如果需要,但通常订单号不变,所以这里只更新 table_id 关联)
-                // 订单明细通过 order_id 关联,不需要单独更新
-            }
-        }
-
-        // 4. 迁移所有未完成的订单(包括可能存在的其他未完成订单)
-        LambdaQueryWrapper<StoreOrder> orderWrapper = new LambdaQueryWrapper<>();
-        orderWrapper.eq(StoreOrder::getTableId, fromTableId);
-        orderWrapper.eq(StoreOrder::getOrderStatus, 0); // 待支付
-        orderWrapper.eq(StoreOrder::getPayStatus, 0); // 未支付
-        orderWrapper.eq(StoreOrder::getDeleteFlag, 0);
-        List<StoreOrder> pendingOrders = this.list(orderWrapper);
-        
-        if (pendingOrders != null && !pendingOrders.isEmpty()) {
-            for (StoreOrder order : pendingOrders) {
-                order.setTableId(toTableId);
-                order.setTableNumber(toTable.getTableNumber());
-                order.setUpdatedUserId(userId);
-                order.setUpdatedTime(new Date());
-            }
-            this.updateBatchById(pendingOrders);
-            log.info("迁移未完成订单, count={}, fromTableId={}, toTableId={}", pendingOrders.size(), fromTableId, toTableId);
-        }
-
-        // 5. 迁移优惠券使用记录
-        LambdaQueryWrapper<StoreCouponUsage> couponUsageWrapper = new LambdaQueryWrapper<>();
-        couponUsageWrapper.eq(StoreCouponUsage::getTableId, fromTableId);
-        couponUsageWrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
-        couponUsageWrapper.in(StoreCouponUsage::getUsageStatus, 0, 1, 2); // 已标记使用、已下单、已支付
-        List<StoreCouponUsage> couponUsages = storeCouponUsageMapper.selectList(couponUsageWrapper);
-        
-        if (couponUsages != null && !couponUsages.isEmpty()) {
-            Date now = new Date();
-            for (StoreCouponUsage usage : couponUsages) {
-                usage.setFromTableId(fromTableId);
-                usage.setTableId(toTableId);
-                usage.setMigrateTime(now);
-                usage.setUpdatedUserId(userId);
-                usage.setUpdatedTime(now);
-            }
-            // 批量更新
-            for (StoreCouponUsage usage : couponUsages) {
-                storeCouponUsageMapper.updateById(usage);
-            }
-            log.info("迁移优惠券使用记录, count={}, fromTableId={}, toTableId={}", couponUsages.size(), fromTableId, toTableId);
-        }
-
-        // 6. 更新桌号表的关联信息
-        // 原桌号:清空 currentOrderId 和 currentCouponId
-        LambdaUpdateWrapper<StoreTable> fromTableWrapper = new LambdaUpdateWrapper<>();
-        fromTableWrapper.eq(StoreTable::getId, fromTableId)
-                .set(StoreTable::getCurrentOrderId, null)
-                .set(StoreTable::getCurrentCouponId, null)
-                .set(StoreTable::getUpdatedTime, new Date());
-        if (userId != null) {
-            fromTableWrapper.set(StoreTable::getUpdatedUserId, userId);
-        }
-        storeTableMapper.update(null, fromTableWrapper);
-        log.info("清空原桌号关联信息, fromTableId={}", fromTableId);
-
-        // 目标桌号:设置 currentOrderId 和 currentCouponId(如果有)
-        if (fromTable.getCurrentOrderId() != null || fromTable.getCurrentCouponId() != null) {
-            LambdaUpdateWrapper<StoreTable> toTableWrapper = new LambdaUpdateWrapper<>();
-            toTableWrapper.eq(StoreTable::getId, toTableId);
-            
-            if (fromTable.getCurrentOrderId() != null) {
-                toTableWrapper.set(StoreTable::getCurrentOrderId, fromTable.getCurrentOrderId());
-            }
-            if (fromTable.getCurrentCouponId() != null) {
-                toTableWrapper.set(StoreTable::getCurrentCouponId, fromTable.getCurrentCouponId());
-            }
-            toTableWrapper.set(StoreTable::getUpdatedTime, new Date());
-            if (userId != null) {
-                toTableWrapper.set(StoreTable::getUpdatedUserId, userId);
-            }
-            storeTableMapper.update(null, toTableWrapper);
-            log.info("设置目标桌号关联信息, toTableId={}, currentOrderId={}, currentCouponId={}", 
-                    toTableId, fromTable.getCurrentOrderId(), fromTable.getCurrentCouponId());
-        }
-
-        log.info("换桌数据迁移完成, fromTableId={}, toTableId={}", fromTableId, toTableId);
-    }
-
-    @Override
-    public shop.alien.entity.store.dto.CartDTO changeTable(Integer fromTableId, Integer toTableId, String changeReason, Integer userId) {
-        log.info("换桌, fromTableId={}, toTableId={}, changeReason={}, userId={}", fromTableId, toTableId, changeReason, userId);
-
-        // 0. 校验:目标桌只能是空桌(空闲且无当前订单)
-        if (fromTableId.equals(toTableId)) {
-            throw new RuntimeException("原桌号与目标桌号不能相同");
-        }
-        StoreTable fromTable = storeTableMapper.selectById(fromTableId);
-        if (fromTable == null) {
-            throw new RuntimeException("原桌号不存在");
-        }
-        StoreTable toTable = storeTableMapper.selectById(toTableId);
-        if (toTable == null) {
-            throw new RuntimeException("目标桌号不存在");
-        }
-        if (!fromTable.getStoreId().equals(toTable.getStoreId())) {
-            throw new RuntimeException("原桌号与目标桌号须在同一门店");
-        }
-        // 空桌:状态为空闲(0)且无当前订单
-        boolean emptyStatus = (toTable.getStatus() == null || toTable.getStatus() == 0);
-        boolean noOrder = (toTable.getCurrentOrderId() == null);
-        if (!emptyStatus || !noOrder) {
-            throw new RuntimeException("只能换到空桌,请选择空闲且无订单的桌号");
-        }
-
-        // 1. 迁移购物车
-        shop.alien.entity.store.dto.CartDTO cart = cartService.migrateCart(fromTableId, toTableId);
-
-        // 2. 迁移所有关联数据(订单、订单变更记录、优惠券使用记录等)
-        migrateTableData(fromTableId, toTableId, userId);
-
-        // 3. 记录换桌日志(fromTable、toTable 已在步骤0中查询)
-        Date now = new Date();
-        StoreTableLog tableLog = new StoreTableLog();
-        tableLog.setStoreId(cart.getStoreId());
-        tableLog.setOrderId(fromTable.getCurrentOrderId()); // 有订单则记录,仅购物车换桌时为 null
-        tableLog.setFromTableId(fromTableId);
-        tableLog.setFromTableNumber(fromTable != null ? fromTable.getTableNumber() : null);
-        tableLog.setToTableId(toTableId);
-        tableLog.setToTableNumber(toTable != null ? toTable.getTableNumber() : null);
-        tableLog.setChangeReason(changeReason);
-        tableLog.setCreatedUserId(userId);
-        tableLog.setCreatedTime(now);
-        tableLog.setUpdatedTime(now);
-        tableLog.setUpdatedUserId(userId);
-        storeTableLogMapper.insert(tableLog);
-
-        // 4. 推送购物车更新消息到新桌号
-        sseService.pushCartUpdate(toTableId, cart);
-
-        log.info("换桌完成, fromTableId={}, toTableId={}", fromTableId, toTableId);
-        return cart;
-    }
-
-    /**
-     * 验证订单是否存在且状态正确(用于支付、取消、加餐、更新优惠券等操作)
-     *
-     * @param orderId      订单ID
-     * @param expectedStatus 期望的订单状态(null表示不校验状态)
-     * @param operation    操作名称(用于错误提示)
-     * @return 订单对象
-     */
-    private StoreOrder validateOrderForOperation(Integer orderId, Integer expectedStatus, String operation) {
-        StoreOrder order = this.getById(orderId);
-        if (order == null) {
-            throw new RuntimeException("订单不存在");
-        }
-        if (expectedStatus != null && order.getOrderStatus() != expectedStatus) {
-            throw new RuntimeException("订单状态不正确,无法" + operation);
-        }
-        return order;
-    }
-
-    /**
-     * 获取当前登录用户信息
-     *
-     * @return 用户ID和手机号的数组 [userId, userPhone]
-     */
-    private Object[] getCurrentUserInfo() {
-        Integer userId = TokenUtil.getCurrentUserId();
-        String userPhone = TokenUtil.getCurrentUserPhone();
-        if (userId == null) {
-            throw new RuntimeException("用户未登录");
-        }
-        return new Object[]{userId, userPhone};
-    }
-
-    /**
-     * 计算优惠金额:根据优惠券类型(满减券或折扣券)计算
-     *
-     * @param coupon           优惠券对象
-     * @param totalWithTableware 订单总金额(含餐具费)
-     * @return 优惠金额
-     */
-    private BigDecimal calculateDiscountAmount(LifeDiscountCoupon coupon, BigDecimal totalWithTableware) {
-        if (coupon == null || totalWithTableware == null || totalWithTableware.compareTo(BigDecimal.ZERO) <= 0) {
-            return BigDecimal.ZERO;
-        }
-
-        Integer couponType = coupon.getCouponType();
-        BigDecimal discountAmount = BigDecimal.ZERO;
-
-        if (couponType != null && couponType == 2) {
-            // 折扣券:根据折扣率计算优惠金额
-            // discountRate: 0-100,例如80表示8折,优惠金额 = 订单金额 * (100 - discountRate) / 100
-            BigDecimal discountRate = coupon.getDiscountRate();
-            if (discountRate != null && discountRate.compareTo(BigDecimal.ZERO) > 0 && discountRate.compareTo(new BigDecimal(100)) <= 0) {
-                // 计算折扣后的金额
-                BigDecimal discountedAmount = totalWithTableware.multiply(discountRate).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
-                // 优惠金额 = 原价 - 折扣后价格
-                discountAmount = totalWithTableware.subtract(discountedAmount);
-            }
-        } else {
-            // 满减券(默认或couponType=1):使用nominalValue
-            discountAmount = coupon.getNominalValue();
-            if (discountAmount == null) {
-                discountAmount = BigDecimal.ZERO;
-            }
-            // 优惠金额不能超过订单总金额
-            if (discountAmount.compareTo(totalWithTableware) > 0) {
-                discountAmount = totalWithTableware;
-            }
-        }
-
-        return discountAmount;
-    }
-
-}

+ 0 - 227
alien-store/src/main/java/shop/alien/store/util/TokenUtil.java

@@ -1,227 +0,0 @@
-package shop.alien.store.util;
-
-import com.alibaba.fastjson.JSONObject;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-import shop.alien.util.common.JwtUtil;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * Token 工具类
- * 用于统一处理 token 的获取和解析
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Slf4j
-public class TokenUtil {
-
-    /**
-     * 去除 token 中的 "Bearer " 前缀
-     *
-     * @param token 原始 token 字符串
-     * @return 去除前缀后的 token
-     */
-    private static String removeBearerPrefix(String token) {
-        if (StringUtils.isBlank(token)) {
-            return token;
-        }
-        // 去除首尾空格
-        token = token.trim();
-        
-        // 去除 "Bearer " 前缀(不区分大小写)
-        if (token.length() > 7 && token.substring(0, 7).equalsIgnoreCase("Bearer ")) {
-            token = token.substring(7).trim();
-        }
-        
-        return token;
-    }
-
-    /**
-     * 从请求头获取当前用户信息
-     * 兼容新的 token 格式(包含 openid)和旧格式
-     *
-     * @return 用户信息 JSONObject,包含 userId、openid、phone、userName 等,如果获取失败返回 null
-     */
-    public static JSONObject getCurrentUserInfo() {
-        try {
-            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
-            if (attributes == null) {
-                return null;
-            }
-
-            HttpServletRequest request = attributes.getRequest();
-            String token = request.getHeader("Authorization");
-            
-            if (StringUtils.isBlank(token)) {
-                return null;
-            }
-
-            // 去除 "Bearer " 前缀
-            token = removeBearerPrefix(token);
-            
-            if (StringUtils.isBlank(token)) {
-                log.warn("Token 去除前缀后为空");
-                return null;
-            }
-
-            // 解析 token,验证格式和签名(与 verifyToken 方法保持一致)
-            io.jsonwebtoken.Claims claims = JwtUtil.parseJWT(token);
-            
-            // 从 token 中提取用户信息(与 verifyToken 方法保持一致)
-            String sub = claims.get("sub").toString();
-            JSONObject userInfo = JSONObject.parseObject(sub);
-            
-            return userInfo;
-        } catch (io.jsonwebtoken.ExpiredJwtException e) {
-            log.warn("Token 已过期: {}", e.getMessage());
-            return null;
-        } catch (io.jsonwebtoken.MalformedJwtException e) {
-            log.error("Token 格式错误: {}", e.getMessage());
-            return null;
-        } catch (io.jsonwebtoken.SignatureException e) {
-            log.error("Token 签名验证失败: {}", e.getMessage());
-            return null;
-        } catch (Exception e) {
-            log.warn("获取当前用户信息失败: {}", e.getMessage());
-            return null;
-        }
-    }
-
-    /**
-     * 获取当前用户ID
-     *
-     * @return 用户ID,如果获取失败返回 null
-     */
-    public static Integer getCurrentUserId() {
-        JSONObject userInfo = getCurrentUserInfo();
-        if (userInfo == null) {
-            log.debug("getCurrentUserInfo() 返回 null,无法获取 userId");
-            return null;
-        }
-        
-        try {
-            String userIdStr = userInfo.getString("userId");
-            if (StringUtils.isBlank(userIdStr)) {
-                log.warn("Token 中的 userId 字段为空或不存在,userInfo keys: {}", userInfo.keySet());
-                return null;
-            }
-            Integer userId = Integer.parseInt(userIdStr);
-            log.debug("成功获取 userId: {}", userId);
-            return userId;
-        } catch (NumberFormatException e) {
-            log.error("解析 userId 失败,userIdStr: {}, 错误: {}", userInfo.getString("userId"), e.getMessage());
-        } catch (Exception e) {
-            log.error("获取 userId 时发生异常: {}", e.getMessage(), e);
-        }
-        
-        return null;
-    }
-
-    /**
-     * 获取当前用户的 openid
-     *
-     * @return openid,如果获取失败返回 null
-     */
-    public static String getCurrentUserOpenid() {
-        JSONObject userInfo = getCurrentUserInfo();
-        if (userInfo == null) {
-            return null;
-        }
-        return userInfo.getString("openid");
-    }
-
-    /**
-     * 获取当前用户的手机号
-     *
-     * @return 手机号,如果获取失败返回 null
-     */
-    public static String getCurrentUserPhone() {
-        JSONObject userInfo = getCurrentUserInfo();
-        if (userInfo == null) {
-            return null;
-        }
-        return userInfo.getString("phone");
-    }
-
-    /**
-     * 检查是否有有效的 token
-     *
-     * @return 如果有有效的 token 返回 true,否则返回 false
-     */
-    public static boolean hasValidToken() {
-        JSONObject userInfo = getCurrentUserInfo();
-        return userInfo != null && userInfo.containsKey("userId");
-    }
-
-    /**
-     * 从 token 字符串直接解析用户信息(用于调试)
-     *
-     * @param token Token 字符串
-     * @return 用户信息 JSONObject,如果解析失败返回 null
-     */
-    public static JSONObject parseToken(String token) {
-        if (StringUtils.isBlank(token)) {
-            log.warn("Token 字符串为空");
-            return null;
-        }
-
-        try {
-            // 去除 "Bearer " 前缀
-            token = removeBearerPrefix(token);
-            
-            if (StringUtils.isBlank(token)) {
-                log.warn("Token 去除前缀后为空");
-                return null;
-            }
-            
-            log.info("开始解析 token: {}", token.length() > 30 ? token.substring(0, 30) + "..." : token);
-
-            // 解析 token
-            io.jsonwebtoken.Claims claims = JwtUtil.parseJWT(token);
-            if (claims == null) {
-                log.warn("Token 解析失败,claims 为 null");
-                return null;
-            }
-
-            log.info("Token claims keys: {}", claims.keySet());
-
-            // 从 token 中提取用户信息
-            Object subObj = claims.get("sub");
-            if (subObj == null) {
-                log.warn("Token claims 中没有 'sub' 字段");
-                return null;
-            }
-
-            String sub;
-            if (subObj instanceof String) {
-                sub = (String) subObj;
-            } else {
-                sub = subObj.toString();
-            }
-
-            log.info("Token sub 内容: {}", sub);
-
-            JSONObject userInfo = JSONObject.parseObject(sub);
-            if (userInfo == null) {
-                log.warn("解析 sub 为 JSONObject 返回 null");
-                return null;
-            }
-
-            log.info("成功解析用户信息: userId={}, openid={}, phone={}, 所有 keys: {}",
-                    userInfo.getString("userId"),
-                    userInfo.getString("openid"),
-                    userInfo.getString("phone"),
-                    userInfo.keySet());
-
-            return userInfo;
-        } catch (Exception e) {
-            log.error("解析 token 失败: {}, 异常类型: {}", e.getMessage(), e.getClass().getName(), e);
-            return null;
-        }
-    }
-}

+ 0 - 375
alien-store/src/main/java/shop/alien/store/util/WeChatMiniProgramUtil.java

@@ -1,375 +0,0 @@
-package shop.alien.store.util;
-
-import com.alibaba.fastjson.JSONObject;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import shop.alien.store.config.BaseRedisService;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-/**
- * 微信小程序工具类
- * 用于调用微信小程序相关接口
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Slf4j
-@Component
-@RequiredArgsConstructor
-public class WeChatMiniProgramUtil {
-
-    @Value("${wechat.miniprogram.appId}")
-    private String appId;
-
-    @Value("${wechat.miniprogram.appSecret}")
-    private String appSecret;
-
-    private final BaseRedisService baseRedisService;
-
-    /**
-     * access_token 缓存键前缀
-     */
-    private static final String ACCESS_TOKEN_CACHE_KEY = "wechat:access_token:";
-    
-    /**
-     * access_token 有效期(秒),微信官方为7200秒,这里设置为7000秒,提前刷新
-     */
-    private static final long ACCESS_TOKEN_EXPIRE_TIME = 7000L;
-
-    /**
-     * 微信小程序登录接口地址
-     */
-    private static final String CODE2SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
-
-    /**
-     * 微信小程序手机号获取接口地址(新版本)
-     */
-    private static final String CODE2VERIFYINFO_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
-
-    /**
-     * 通过 code 获取 openid 和 session_key
-     *
-     * @param code 小程序端通过 wx.login() 获取的 code
-     * @return WeChatSessionInfo 包含 openid、session_key、unionid 等信息
-     */
-    public WeChatSessionInfo code2Session(String code) {
-        String url = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
-                CODE2SESSION_URL, appId, appSecret, code);
-
-        HttpClient httpClient = HttpClients.createDefault();
-        HttpGet httpGet = new HttpGet(url);
-
-        try {
-            HttpResponse response = httpClient.execute(httpGet);
-            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
-            log.info("微信 code2session 响应: {}", responseBody);
-
-            JSONObject jsonObject = JSONObject.parseObject(responseBody);
-
-            // 检查是否有错误
-            if (jsonObject.containsKey("errcode")) {
-                Integer errcode = jsonObject.getInteger("errcode");
-                String errmsg = jsonObject.getString("errmsg");
-                
-                // 将错误信息保存到返回对象中,方便上层处理
-                WeChatSessionInfo errorInfo = new WeChatSessionInfo();
-                errorInfo.setErrcode(errcode);
-                errorInfo.setErrmsg(errmsg);
-                
-                // 根据错误码记录详细的错误信息
-                String errorDetail = getErrorDetail(errcode, errmsg);
-                log.error("微信 code2session 失败: errcode={}, errmsg={}, 详情={}", errcode, errmsg, errorDetail);
-                return errorInfo;
-            }
-
-            // 解析返回数据
-            WeChatSessionInfo sessionInfo = new WeChatSessionInfo();
-            sessionInfo.setOpenid(jsonObject.getString("openid"));
-            sessionInfo.setSessionKey(jsonObject.getString("session_key"));
-            sessionInfo.setUnionid(jsonObject.getString("unionid"));
-
-            return sessionInfo;
-        } catch (IOException e) {
-            log.error("调用微信 code2session 接口异常", e);
-            return null;
-        }
-    }
-
-    /**
-     * 获取微信错误码的详细说明
-     */
-    private String getErrorDetail(Integer errcode, String errmsg) {
-        if (errcode == null) {
-            return "未知错误";
-        }
-        
-        switch (errcode) {
-            case 40029:
-                return "code无效(可能原因:1. code已使用过,每个code只能使用一次;2. code已过期,有效期5分钟;3. code格式错误;4. appId或appSecret配置错误)";
-            case 45011:
-                return "频率限制,每个用户每分钟最多调用5次";
-            case 40226:
-                return "高风险等级用户,需要用户进行验证";
-            case 40013:
-                return "appId无效,请检查Nacos配置中的wechat.miniprogram.appId";
-            case 40125:
-                return "appSecret无效,请检查Nacos配置中的wechat.miniprogram.appSecret";
-            case -1:
-                return "系统繁忙,请稍后重试";
-            default:
-                return String.format("微信接口错误,错误码:%d,错误信息:%s", errcode, errmsg);
-        }
-    }
-
-    /**
-     * 解密微信小程序加密数据(手机号等)
-     * 使用 AES-128-CBC 算法,使用 session_key 作为密钥
-     *
-     * @param encryptedData 加密数据(Base64编码)
-     * @param sessionKey    session_key(Base64编码)
-     * @param iv           初始向量(Base64编码)
-     * @return 解密后的JSON字符串,包含手机号等信息
-     */
-    public String decryptData(String encryptedData, String sessionKey, String iv) {
-        try {
-            if (encryptedData == null || encryptedData.isEmpty()) {
-                log.warn("加密数据为空,无法解密");
-                return null;
-            }
-            if (sessionKey == null || sessionKey.isEmpty()) {
-                log.warn("session_key为空,无法解密");
-                return null;
-            }
-            if (iv == null || iv.isEmpty()) {
-                log.warn("初始向量为空,无法解密");
-                return null;
-            }
-
-            // Base64解码
-            byte[] dataByte = Base64.decodeBase64(encryptedData);
-            byte[] keyByte = Base64.decodeBase64(sessionKey);
-            byte[] ivByte = Base64.decodeBase64(iv);
-
-            // AES-128-CBC 解密
-            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
-            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
-            IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
-            cipher.init(Cipher.DECRYPT_MODE, spec, ivSpec);
-
-            byte[] decrypted = cipher.doFinal(dataByte);
-            String result = new String(decrypted, StandardCharsets.UTF_8);
-            
-            log.info("微信加密数据解密成功");
-            return result;
-        } catch (Exception e) {
-            log.error("微信加密数据解密失败: encryptedData={}, error={}", 
-                    encryptedData != null ? encryptedData.substring(0, Math.min(20, encryptedData.length())) : "null", 
-                    e.getMessage(), e);
-            return null;
-        }
-    }
-
-    /**
-     * 从解密后的数据中提取手机号(旧版本,已废弃)
-     *
-     * @param decryptedData 解密后的JSON字符串
-     * @return 手机号
-     */
-    @Deprecated
-    public String extractPhoneNumber(String decryptedData) {
-        try {
-            if (decryptedData == null || decryptedData.isEmpty()) {
-                return null;
-            }
-            
-            JSONObject jsonObject = JSONObject.parseObject(decryptedData);
-            String phoneNumber = jsonObject.getString("phoneNumber");
-            
-            log.info("从解密数据中提取手机号: {}", phoneNumber != null ? phoneNumber.substring(0, Math.min(7, phoneNumber.length())) + "****" : "null");
-            return phoneNumber;
-        } catch (Exception e) {
-            log.error("提取手机号失败: {}", e.getMessage(), e);
-            return null;
-        }
-    }
-
-    /**
-     * 通过手机号凭证 code 获取手机号(新版本API)
-     * 使用 code2Verifyinfo 接口
-     *
-     * @param phoneCode 手机号凭证 code(通过wx.getPhoneNumber()获取)
-     * @return 手机号,如果获取失败返回null
-     */
-    public String getPhoneNumberByCode(String phoneCode) {
-        if (phoneCode == null || phoneCode.isEmpty()) {
-            log.warn("手机号凭证code为空");
-            return null;
-        }
-
-        try {
-            // 获取 access_token
-            String accessToken = getAccessToken();
-            if (accessToken == null || accessToken.isEmpty()) {
-                log.error("获取access_token失败,无法调用手机号接口");
-                return null;
-            }
-
-            // 构建请求URL
-            String url = String.format("%s?access_token=%s", CODE2VERIFYINFO_URL, accessToken);
-            
-            // 构建请求体
-            JSONObject requestBody = new JSONObject();
-            requestBody.put("code", phoneCode);
-
-            // 使用HttpClient发送POST请求
-            HttpClient httpClient = HttpClients.createDefault();
-            HttpPost httpPost = new HttpPost(url);
-            httpPost.setHeader("Content-Type", "application/json");
-            httpPost.setEntity(new StringEntity(requestBody.toJSONString(), "UTF-8"));
-
-            HttpResponse response = httpClient.execute(httpPost);
-            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
-            log.info("微信 code2Verifyinfo 响应: {}", responseBody);
-
-            JSONObject jsonObject = JSONObject.parseObject(responseBody);
-
-            // 检查是否有错误(errcode 为 0 表示成功,非 0 才视为失败)
-            if (jsonObject.containsKey("errcode")) {
-                Integer errcode = jsonObject.getInteger("errcode");
-                if (errcode != null && errcode != 0) {
-                    String errmsg = jsonObject.getString("errmsg");
-                    log.error("微信 code2Verifyinfo 失败: errcode={}, errmsg={}", errcode, errmsg);
-                    return null;
-                }
-            }
-
-            // 解析返回数据
-            JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
-            if (phoneInfo != null) {
-                String phoneNumber = phoneInfo.getString("phoneNumber");
-                log.info("成功获取手机号");
-                return phoneNumber;
-            }
-
-            return null;
-        } catch (Exception e) {
-            log.error("调用微信 code2Verifyinfo 接口异常", e);
-            return null;
-        }
-    }
-
-    /**
-     * 获取微信 access_token(带缓存机制)
-     * access_token有效期为7200秒,这里缓存7000秒,提前刷新避免过期
-     * 
-     * @return access_token,获取失败返回null
-     */
-    private String getAccessToken() {
-        // 1. 先从缓存获取
-        String cacheKey = ACCESS_TOKEN_CACHE_KEY + appId;
-        String cachedToken = baseRedisService.getString(cacheKey);
-        if (cachedToken != null && !cachedToken.isEmpty()) {
-            log.debug("从缓存获取access_token成功");
-            return cachedToken;
-        }
-
-        // 2. 缓存未命中,请求微信接口
-        try {
-            String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
-                    appId, appSecret);
-            
-            HttpClient httpClient = HttpClients.createDefault();
-            HttpGet httpGet = new HttpGet(url);
-            HttpResponse response = httpClient.execute(httpGet);
-            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
-            
-            log.info("微信获取access_token响应: {}", responseBody);
-            
-            JSONObject jsonObject = JSONObject.parseObject(responseBody);
-            if (jsonObject.containsKey("access_token")) {
-                String accessToken = jsonObject.getString("access_token");
-                
-                // 3. 存入缓存(有效期7000秒,提前刷新)
-                baseRedisService.setString(cacheKey, accessToken, ACCESS_TOKEN_EXPIRE_TIME);
-                log.info("成功获取access_token并存入缓存");
-                return accessToken;
-            } else {
-                Integer errcode = jsonObject.getInteger("errcode");
-                String errmsg = jsonObject.getString("errmsg");
-                log.error("获取access_token失败: errcode={}, errmsg={}", errcode, errmsg);
-                return null;
-            }
-        } catch (Exception e) {
-            log.error("获取access_token异常", e);
-            return null;
-        }
-    }
-
-    /**
-     * 微信会话信息
-     */
-    public static class WeChatSessionInfo {
-        private String openid;
-        private String sessionKey;
-        private String unionid;
-        private Integer errcode;
-        private String errmsg;
-
-        public String getOpenid() {
-            return openid;
-        }
-
-        public void setOpenid(String openid) {
-            this.openid = openid;
-        }
-
-        public String getSessionKey() {
-            return sessionKey;
-        }
-
-        public void setSessionKey(String sessionKey) {
-            this.sessionKey = sessionKey;
-        }
-
-        public String getUnionid() {
-            return unionid;
-        }
-
-        public void setUnionid(String unionid) {
-            this.unionid = unionid;
-        }
-
-        public Integer getErrcode() {
-            return errcode;
-        }
-
-        public void setErrcode(Integer errcode) {
-            this.errcode = errcode;
-        }
-
-        public String getErrmsg() {
-            return errmsg;
-        }
-
-        public void setErrmsg(String errmsg) {
-            this.errmsg = errmsg;
-        }
-    }
-}
-

+ 0 - 65
alien-store/src/main/java/shop/alien/store/util/WeChatPayUtil.java

@@ -1,65 +0,0 @@
-package shop.alien.store.util;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.binary.Base64;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.GCMParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.StandardCharsets;
-
-/**
- * 微信支付工具类
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Slf4j
-public class WeChatPayUtil {
-    // TODO: 实现微信支付相关工具方法
-
-    // AES-GCM模式的TAG长度(微信固定为128位/16字节)
-    private static final int GCM_TAG_LENGTH = 128;
-    // AES-256算法要求密钥长度为32字节(APIv3密钥必须是32位)
-    private static final int API_V3_KEY_LENGTH = 32;
-
-    /**
-     * 解密微信支付resource字段密文
-     * @param apiV3Key 商户平台设置的APIv3密钥(32位字符串)
-     * @param nonce resource.nonce(加密随机串)
-     * @param associatedData resource.associated_data(关联数据)
-     * @param ciphertext resource.ciphertext(Base64编码的密文)
-     * @return 解密后的明文(JSON格式业务信息)
-     * @throws Exception 解密异常(密钥错误、参数非法等)
-     */
-    public static String decrypt(String apiV3Key, String nonce, String associatedData, String ciphertext) throws Exception {
-        // 1. 校验APIv3密钥长度(必须32字节)
-        if (apiV3Key == null || apiV3Key.length() != API_V3_KEY_LENGTH) {
-            throw new IllegalArgumentException("APIv3密钥必须是32位字符串");
-        }
-
-        // 2. 转换密钥为SecretKeySpec(AES-256)
-        SecretKeySpec secretKeySpec = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
-
-        // 3. Base64解密密文
-        byte[] ciphertextBytes = Base64.decodeBase64(ciphertext);
-
-        // 4. 初始化GCM参数(nonce为16字节?微信实际是12字节,符合rfc5116)
-        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, nonce.getBytes(StandardCharsets.UTF_8));
-
-        // 5. 初始化AES-GCM解密器
-        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
-        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
-
-        // 6. 设置关联数据(AEAD附加数据)
-        cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));
-
-        // 7. 执行解密
-        byte[] plaintextBytes = cipher.doFinal(ciphertextBytes);
-
-        // 8. 转换为UTF-8明文(JSON格式)
-        return new String(plaintextBytes, StandardCharsets.UTF_8);
-    }
-}
-

+ 0 - 76
alien-store/src/main/java/shop/alien/store/vo/DiningUserVo.java

@@ -1,76 +0,0 @@
-package shop.alien.store.vo;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * 点餐用户VO
- * 基于 LifeUser 表
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("点餐用户信息")
-public class DiningUserVo {
-
-    @ApiModelProperty("用户ID")
-    private Long id;
-
-    @ApiModelProperty("用户昵称")
-    private String nickName;
-
-    @ApiModelProperty("用户头像")
-    private String avatarUrl;
-
-    @ApiModelProperty("手机号")
-    private String phone;
-
-    @ApiModelProperty("性别")
-    private String gender;
-
-    @ApiModelProperty("生日")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
-    private Date birthday;
-
-    @ApiModelProperty("真实姓名")
-    private String realName;
-
-    @ApiModelProperty("省份")
-    private String province;
-
-    @ApiModelProperty("城市")
-    private String city;
-
-    @ApiModelProperty("区县")
-    private String district;
-
-    @ApiModelProperty("详细地址")
-    private String address;
-
-    @ApiModelProperty("个人简介")
-    private String jianjie;
-
-    @ApiModelProperty("用户状态:0-正常,1-禁用")
-    private Integer status;
-
-    @ApiModelProperty("创建时间")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date createdTime;
-
-    @ApiModelProperty("最后登录时间")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date lastLoginTime;
-
-    @ApiModelProperty("JWT Token")
-    private String token;
-
-    @ApiModelProperty("微信OpenID")
-    private String openId;
-}
-

+ 0 - 40
alien-store/src/main/java/shop/alien/store/vo/TokenVerifyVo.java

@@ -1,40 +0,0 @@
-package shop.alien.store.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-/**
- * Token 校验结果VO
- *
- * @author ssk
- * @version 1.0
- * @date 2024/12/4
- */
-@Data
-@ApiModel("Token校验结果")
-public class TokenVerifyVo {
-
-    @ApiModelProperty(value = "Token是否有效")
-    private Boolean valid;
-
-    @ApiModelProperty(value = "用户ID")
-    private Long userId;
-
-    @ApiModelProperty(value = "用户手机号")
-    private String phone;
-
-    @ApiModelProperty(value = "用户昵称")
-    private String nickName;
-
-    @ApiModelProperty(value = "微信OpenID")
-    private String openid;
-
-    @ApiModelProperty(value = "Token过期时间")
-    private Date expirationTime;
-
-    @ApiModelProperty(value = "验证失败原因")
-    private String reason;
-}

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels