Ver Fonte

Merge remote-tracking branch 'origin/master_exclusive_shop_20250718' into master_exclusive_shop_20250718

csy há 3 semanas atrás
pai
commit
86b1fc4fa8
46 ficheiros alterados com 895 adições e 297 exclusões
  1. 10 0
      fs-admin/src/main/java/com/fs/core/config/DruidConfig.java
  2. 9 2
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  3. 15 0
      fs-admin/src/main/java/com/fs/store/controller/FsStoreAfterSalesController.java
  4. 13 0
      fs-admin/src/main/java/com/fs/store/controller/FsStoreHealthOrderController.java
  5. 13 3
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  6. 71 44
      fs-admin/src/main/java/com/fs/task/LiveTask.java
  7. 12 7
      fs-admin/src/main/java/com/fs/task/StoreTask.java
  8. 9 4
      fs-admin/src/main/resources/application-dev.yml
  9. 5 0
      fs-admin/src/main/resources/application-druid.yml
  10. 16 2
      fs-admin/src/main/resources/application.yml
  11. 77 0
      fs-admin/src/main/resources/logback-spring.xml
  12. 4 4
      fs-api/src/main/resources/application-dev.yml
  13. 6 1
      fs-common/src/main/java/com/fs/common/enums/DataSourceType.java
  14. 27 0
      fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java
  15. 2 1
      fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java
  16. 10 0
      fs-company/src/main/java/com/fs/core/config/DruidConfig.java
  17. 14 0
      fs-company/src/main/java/com/fs/store/controller/FsStoreAfterSalesController.java
  18. 18 3
      fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  19. 8 4
      fs-company/src/main/resources/application-dev.yml
  20. 5 0
      fs-company/src/main/resources/application-druid.yml
  21. 5 5
      fs-live-mq/src/main/resources/application-dev.yml
  22. 5 5
      fs-live-socket/src/main/resources/application-dev.yml
  23. 9 8
      fs-service-system/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java
  24. 2 0
      fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderMapper.java
  25. 2 0
      fs-service-system/src/main/java/com/fs/live/service/ILiveOrderService.java
  26. 13 42
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  27. 3 0
      fs-service-system/src/main/java/com/fs/live/vo/LiveOrderQueryVO.java
  28. 38 0
      fs-service-system/src/main/java/com/fs/store/config/ShippingTemplateRedisConfig.java
  29. 19 0
      fs-service-system/src/main/java/com/fs/store/domain/FsStoreAfterSales.java
  30. 32 0
      fs-service-system/src/main/java/com/fs/store/listener/ShippingTemplateRefreshListener.java
  31. 16 4
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderItemMapper.java
  32. 61 14
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java
  33. 9 0
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java
  34. 77 0
      fs-service-system/src/main/java/com/fs/store/service/ShippingTemplateRefreshService.java
  35. 31 3
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesFreeServiceImpl.java
  36. 31 3
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesRegionServiceImpl.java
  37. 8 45
      fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesServiceImpl.java
  38. 3 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderItemServiceImpl.java
  39. 18 9
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  40. 88 75
      fs-service-system/src/main/java/com/fs/store/strategy/ShippingTemplateManager.java
  41. 43 0
      fs-service-system/src/main/java/com/fs/store/util/OrderPhoneSearchHelper.java
  42. 2 2
      fs-service-system/src/main/resources/application-config.yml
  43. 14 1
      fs-service-system/src/main/resources/mapper/live/LiveOrderMapper.xml
  44. 3 0
      fs-service-system/src/main/resources/mapper/store/FsStoreAfterSalesMapper.xml
  45. 15 2
      fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml
  46. 4 4
      fs-user-app/src/main/resources/application-dev.yml

+ 10 - 0
fs-admin/src/main/java/com/fs/core/config/DruidConfig.java

@@ -50,6 +50,15 @@ public class DruidConfig
         return druidProperties.dataSource(dataSource);
     }
 
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.huyi")
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.huyi", name = "enabled", havingValue = "true", matchIfMissing = true)
+    public DataSource huyiDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
     @Bean(name = "dynamicDataSource")
     @Primary
     public DynamicDataSource dataSource(DataSource masterDataSource)
@@ -57,6 +66,7 @@ public class DruidConfig
         Map<Object, Object> targetDataSources = new HashMap<>();
         targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
         setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+        setDataSource(targetDataSources, DataSourceType.HUYI.name(), "huyiDataSource");
         return new DynamicDataSource(masterDataSource, targetDataSources);
     }
 

+ 9 - 2
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -8,6 +8,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -115,6 +116,10 @@ public class LiveOrderController extends BaseController
     @Autowired
     private PayService ybPayService;
 
+
+    @Autowired
+    private FsStoreDeliversService fsStoreDeliversService;
+
     /**
      * 查询订单列表
      */
@@ -331,7 +336,7 @@ public class LiveOrderController extends BaseController
     public R getPhone(@PathVariable("id") Long id)
     {
         LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(id));
-        String userPhone = order.getUserPhone();
+        String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
         return R.ok().put("userPhone",userPhone);
     }
 
@@ -421,6 +426,7 @@ public class LiveOrderController extends BaseController
         return liveOrderService.finishOrder(param.getOrderId());
     }
 
+
     /**
      * 修改物流
      * @param deliveryDTO
@@ -430,7 +436,8 @@ public class LiveOrderController extends BaseController
     @PreAuthorize("@ss.hasPermi('live:liveOrder:editDeliveryId')")
     @PutMapping("/editDeliveryId")
     public AjaxResult editDeliveryId(@RequestBody FsStoreDelivers deliveryDTO) {
-        liveOrderService.editLiveOrderDeliveryId(deliveryDTO);
+        deliveryDTO.setType(1);
+        fsStoreDeliversService.editDeliveryId(deliveryDTO);
         return AjaxResult.success();
     }
 

+ 15 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStoreAfterSalesController.java

@@ -1,17 +1,20 @@
 package com.fs.store.controller;
 
 import java.text.ParseException;
+import java.util.ArrayList;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
 import com.fs.express.FsStoreDeliversService;
 import com.fs.express.cache.FsStoreDeliversCacheService;
 import com.fs.store.domain.*;
 
+import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.param.FsStoreAfterSalesAudit1Param;
 import com.fs.store.param.FsStoreAfterSalesAudit2Param;
 import com.fs.store.param.FsStoreAfterSalesCancelParam;
@@ -58,6 +61,9 @@ public class FsStoreAfterSalesController extends BaseController
 
     @Autowired
     private FsStoreDeliversService fsStoreDeliversService;
+
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
     /**
      * 查询售后记录列表
      */
@@ -65,6 +71,15 @@ public class FsStoreAfterSalesController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(FsStoreAfterSales fsStoreAfterSales)
     {
+        if (fsStoreAfterSales.getHuYiUserId() != null) {
+            String unionId = fsStoreOrderMapper.selectUnionIdByHyUserId(fsStoreAfterSales.getHuYiUserId());
+            if (StringUtils.isEmpty(unionId)) {
+                return getDataTable(new ArrayList<>());
+            }
+
+            fsStoreAfterSales.setUnionId(unionId);
+        }
+
         startPage();
         List<FsStoreAfterSalesVO> list = fsStoreAfterSalesService.selectFsStoreAfterSalesListVO(fsStoreAfterSales);
         for (FsStoreAfterSalesVO vo : list){

+ 13 - 0
fs-admin/src/main/java/com/fs/store/controller/FsStoreHealthOrderController.java

@@ -13,6 +13,7 @@ import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.store.cache.IFsStoreProductCacheService;
 import com.fs.store.dto.StoreOrderProductDTO;
+import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.param.FsStoreOrderParam;
 import com.fs.store.service.*;
 import com.fs.store.vo.FsStoreOrderExportVO;
@@ -40,12 +41,24 @@ public class FsStoreHealthOrderController extends BaseController {
     @Autowired
     private IFsStoreProductCacheService fsStoreProductCacheService;
 
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
+
     /**
      * 查询健康商城订单列表
      */
     @PreAuthorize("@ss.hasPermi('store:healthStoreOrder:list')")
     @GetMapping("/healthList")
     public TableDataInfo healthStoreList(FsStoreOrderParam param) {
+        if (param.getHuYiUserId() != null) {
+            String unionId = fsStoreOrderMapper.selectUnionIdByHyUserId(param.getHuYiUserId());
+            if (StringUtils.isEmpty(unionId)) {
+                return getDataTable(new ArrayList<>());
+            }
+
+            param.setUnionId(unionId);
+        }
+
         startPage();
         if(!StringUtils.isEmpty(param.getCreateTimeRange())){
             param.setCreateTimeList(param.getCreateTimeRange().split("--"));

+ 13 - 3
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -8,6 +8,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
@@ -92,6 +93,15 @@ public class FsStoreOrderController extends BaseController {
     @PreAuthorize("@ss.hasPermi('store:storeOrder:list')")
     @GetMapping("/list")
     public TableDataInfo list(FsStoreOrderParam param) {
+        if (param.getHuYiUserId() != null) {
+            String unionId = fsStoreOrderMapper.selectUnionIdByHyUserId(param.getHuYiUserId());
+            if (StringUtils.isEmpty(unionId)) {
+                return getDataTable(new ArrayList<>());
+            }
+
+            param.setUnionId(unionId);
+        }
+
         startPage();
         if(!StringUtils.isEmpty(param.getCreateTimeRange())){
             param.setCreateTimeList(param.getCreateTimeRange().split("--"));
@@ -307,11 +317,11 @@ public class FsStoreOrderController extends BaseController {
     @GetMapping(value = "/{id}")
     public R getInfo(@PathVariable("id") Long id) {
         FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
+        order.setUserPhone(PhoneUtils.normalizePhoneForDisplay(order.getUserPhone()));
         order.setUserAddress(ParseUtils.parseAddress(order.getUserAddress()));
         FsUser user = userService.selectFsUserById(order.getUserId());
         if (user!=null){
-            user.setPhone(ParseUtils.parsePhone(user.getPhone()));
+            user.setPhone(PhoneUtils.normalizePhoneForDisplay(user.getPhone()));
         }
 
         FsStoreOrderItem itemMap = new FsStoreOrderItem();
@@ -365,7 +375,7 @@ public class FsStoreOrderController extends BaseController {
     public R getPhone(@PathVariable("id") Long id)
     {
         FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-        String userPhone = order.getUserPhone();
+        String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
         return R.ok().put("userPhone",userPhone);
     }
 

+ 71 - 44
fs-admin/src/main/java/com/fs/task/LiveTask.java

@@ -7,10 +7,10 @@ import com.fs.erp.domain.ErpOrderQuery;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.FsJstAftersalePushService;
-import com.fs.erp.service.IErpOrderService;
-import com.fs.erp.utils.ErpContextHolder;
+import com.fs.erp.service.impl.JSTErpOrderServiceImpl;
 import com.fs.express.FsStoreDeliversService;
 import com.fs.common.utils.StringUtils;
+import com.google.common.collect.Lists;
 import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
 import com.fs.live.domain.LiveOrderPayment;
@@ -30,7 +30,6 @@ import com.fs.store.mapper.*;
 import com.fs.store.param.LiveAfterSalesAudit1Param;
 import com.fs.store.service.*;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang.ObjectUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +38,7 @@ import org.springframework.stereotype.Component;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -52,6 +52,9 @@ import static com.fs.live.utils.redis.RedisBatchHandler.CONSUME_INTERVAL;
 public class LiveTask {
     Logger logger = LoggerFactory.getLogger(LiveTask.class);
 
+    /** 聚水潭发货查询每批 o_id 数量 */
+    private static final int DELIVERY_QUERY_BATCH_SIZE = 30;
+    private static final String JST_SHOP_ID = "18675245";
 
     @Autowired
     private ILiveOrderService liveOrderService;
@@ -67,8 +70,7 @@ public class LiveTask {
 
 
     @Autowired
-    private IErpOrderService erpOrderService;
-
+    private JSTErpOrderServiceImpl jstErpOrderService;
 
     @Autowired
     private IFsExpressService expressService;
@@ -77,10 +79,6 @@ public class LiveTask {
     @Autowired
     private ILiveOrderLogsService orderLogsService;
 
-
-    @Autowired
-    private FsWarehousesMapper fsWarehousesMapper;
-
     @Autowired
     public FsJstAftersalePushService fsJstAftersalePushService;
     @Autowired
@@ -166,57 +164,86 @@ public class LiveTask {
      * 发货任务
      */
     @QuartzRunnable(name = "发货任务")
-    public void deliveryOp() {
+    public void deliveryOp() throws InterruptedException {
         List<LiveOrder> list = liveOrderService.selectDeliverPenddingData();
 
-        for (LiveOrder order : list) {
-            String orderCode = order.getOrderCode();
-            ErpOrderQueryRequert request = new ErpOrderQueryRequert();
-            request.setCode(order.getExtendOrderId());
-
-            try {
-                // 根据仓库code找erp
-                if (com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())) {
-                    String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
-                    ErpContextHolder.setErpType(erp);
-                }
-                ErpOrderQueryResponse response = erpOrderService.getOrderLive(request);
-                if (CollectionUtils.isNotEmpty(response.getOrders())) {
-                    for (ErpOrderQuery orderQuery : response.getOrders()) {
-                        if (CollectionUtils.isNotEmpty(orderQuery.getDeliverys())) {
-                            // 部分发货或者全部发货
-                            if (ObjectUtils.equals(orderQuery.getDelivery_state(), 1) || ObjectUtils.equals(orderQuery.getDelivery_state(), 2)) {
-
-                                orderLogsService.create(order.getOrderId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
-                                        OrderLogEnum.DELIVERY_GOODS.getDesc());
+        ArrayList<Long> oIds = new ArrayList<>();
+        for (LiveOrder liveOrder : list) {
+            if (StringUtils.isNotEmpty(liveOrder.getExtendOrderId())) {
+                oIds.add(Long.parseLong(liveOrder.getExtendOrderId()));
+            }
+        }
+        if (!CollectionUtils.isEmpty(oIds)) {
+            jstErpOrderDelivery(oIds);
+        }
+    }
 
-                                for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+    private void jstErpOrderDelivery(List<Long> oIds) throws InterruptedException {
+        if (CollectionUtils.isEmpty(oIds)) {
+            return;
+        }
 
-                                    FsExpress express = expressService.selectFsExpressByOmsCode(delivery.getExpress_code());
+        List<List<Long>> batches = Lists.partition(oIds, DELIVERY_QUERY_BATCH_SIZE);
+        for (List<Long> batch : batches) {
+            List<String> extendIds = new ArrayList<>();
+            for (Long oId : batch) {
+                extendIds.add(oId.toString());
+            }
+            int pageIndex = 1;
+            boolean hasNext;
+            do {
+                Thread.sleep(300);
+                ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+                request.setPage_size(100);
+                request.setPage_index(pageIndex);
+                request.setShop_id(JST_SHOP_ID);
+                request.setO_ids(batch);
+
+                ErpOrderQueryResponse response = jstErpOrderService.getOrderLive(request);
+                hasNext = response.hasNextSafe();
+                liveOrderService.updateUpdateTimeByExtendIds(extendIds);
+
+                if (response.getOrders() != null) {
+                    for (ErpOrderQuery orderQuery : response.getOrders()) {
+                        if (orderQuery.getDeliverys() == null || orderQuery.getDeliverys().isEmpty()) {
+                            continue;
+                        }
+                        for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                            if (!delivery.getDelivery() || org.apache.commons.lang3.StringUtils.isEmpty(delivery.getMail_no())) {
+                                continue;
+                            }
+                            LiveOrder liveOrder = liveOrderService.selectLiveOrderByOrderCode(orderQuery.getCode());
+                            if (liveOrder == null) {
+                                logger.warn("直播发货任务未找到订单 orderCode={}", orderQuery.getCode());
+                                continue;
+                            }
+                            orderLogsService.create(liveOrder.getOrderId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
+                                    OrderLogEnum.DELIVERY_GOODS.getDesc());
+                            try {
+                                for (ErpDeliverys deli : orderQuery.getDeliverys()) {
+                                    FsExpress express = expressService.selectFsExpressByOmsCode(deli.getExpress_code());
                                     if (express == null) {
-                                        logger.warn("当前express_code: {} 不存在!", delivery.getExpress_code());
+                                        logger.error("当前express_code: {} 不存在!", deli.getExpress_code());
                                         continue;
                                     }
-
-                                    if (delivery.getDelivery()) {
-                                        liveOrderService.deliveryOrder(orderCode, delivery.getMail_no(),
-                                                delivery.getExpress_code(), delivery.getExpress_name());
+                                    if (deli.getDelivery()) {
+                                        liveOrderService.deliveryOrder(orderQuery.getCode(), deli.getMail_no(),
+                                                deli.getExpress_code(), deli.getExpress_name());
                                     }
                                 }
-
-                                logger.info("订单 {} 发货信息同步成功", order.getOrderCode());
+                                logger.info("直播订单 {} 发货信息同步成功", orderQuery.getCode());
+                            } catch (Exception e) {
+                                logger.error("同步直播订单发货状态失败 orderCode={} mailNo={}",
+                                        orderQuery.getCode(), delivery.getMail_no(), e);
                             }
                         }
                     }
                 }
-            } catch (Exception e) {
-                logger.error(String.format("[发货任务]调用erp查询接口失败!原因: %s", e));
-            }
-
+                pageIndex++;
+            } while (hasNext);
         }
     }
 
-
     /**
      * 同步近三天直播订单关联的APP用户数据
      */

+ 12 - 7
fs-admin/src/main/java/com/fs/task/StoreTask.java

@@ -69,6 +69,11 @@ import static com.fs.store.constants.StoreConstants.DELIVERY;
 @Component("storeTask")
 public class StoreTask {
     Logger logger = LoggerFactory.getLogger(StoreTask.class);
+
+    /** 聚水潭发货查询每批 o_id 数量 */
+    private static final int DELIVERY_QUERY_BATCH_SIZE = 30;
+    private static final String JST_SHOP_ID = "18675245";
+
     @Autowired
     private RedisTemplate redisTemplate;
     @Autowired
@@ -255,9 +260,12 @@ public class StoreTask {
     private void jstErpOrderDelivery(List<Long> o_ids) throws InterruptedException {
         if (org.springframework.util.CollectionUtils.isEmpty(o_ids)) return;
 
-        List<List<Long>> batches = Lists.partition(o_ids, 100);
-        List<String> extendIds = new ArrayList<>();
+        List<List<Long>> batches = Lists.partition(o_ids, DELIVERY_QUERY_BATCH_SIZE);
         for (List<Long> batch : batches) {
+            List<String> extendIds = new ArrayList<>();
+            for (Long oId : batch) {
+                extendIds.add(oId.toString());
+            }
             int pageIndex = 1;
             boolean has_next = false;
             do {
@@ -265,14 +273,11 @@ public class StoreTask {
                 ErpOrderQueryRequert request = new ErpOrderQueryRequert();
                 request.setPage_size(100);
                 request.setPage_index(pageIndex);
-                request.setShop_id("18675245");
-                request.setO_ids(batch); // 设置当前批次
+                request.setShop_id(JST_SHOP_ID);
+                request.setO_ids(batch);
 
                 ErpOrderQueryResponse response = jstErpOrderService.getOrder(request);
                 has_next = response.hasNextSafe();
-                for (Long l : batch) {
-                    extendIds.add(l.toString());
-                }
                 orderService.updateUpdateTimeByExtendIds(extendIds);
 
                 if (response.getOrders() != null) {

+ 9 - 4
fs-admin/src/main/resources/application-dev.yml

@@ -30,14 +30,19 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://10.0.0.6:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://10.0.0.3:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
+            # huyi 数据源
+            huyi:
+                url: jdbc:mysql://1.14.207.209:8008/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
-                password: Ylrz_1q2w3e4r5t6y
+                password: X7k#9mPq$2LvR&5n
             # 初始连接数
             initialSize: 5
             # 最小连接池数量
@@ -87,4 +92,4 @@ rocketmq:
     consumer:
         group: common-group
         access-key: ak16b45v4p9n150d89395b3c # 替换为实际的 accessKey
-        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey
+        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey

+ 5 - 0
fs-admin/src/main/resources/application-druid.yml

@@ -38,6 +38,11 @@ spring:
                 url:
                 username:
                 password:
+
+            huyi:
+                url: jdbc:mysql://1.14.207.209:8008/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: root
+                password: X7k#9mPq$2LvR&5n
             # 初始连接数
             initialSize: 5
             # 最小连接池数量

+ 16 - 2
fs-admin/src/main/resources/application.yml

@@ -27,19 +27,33 @@ server:
   tomcat:
     # tomcat的URI编码
     uri-encoding: UTF-8
-    # tomcat最大线程数,默认为200
     max-threads: 800
     # Tomcat启动初始化的线程数,默认值25
     min-spare-threads: 30
 
-# 日志配置
+# 日志配置(文件与控制台均为 UTF-8)
 logging:
+  file:
+    path: logs
+  logback:
+    rollingpolicy:
+      # 单文件大小上限(200MB~500MB,按需调整)
+      max-file-size: 300MB
+      # 归档保留天数
+      max-history: 60
+      # 所有归档日志总大小上限
+      total-size-cap: 20GB
   level:
     com.fs: warn
     org.springframework: warn
 
 # Spring配置
 spring:
+  http:
+    encoding:
+      charset: UTF-8
+      enabled: true
+      force: true
   mvc:
     async:
       request-timeout: 30000

+ 77 - 0
fs-admin/src/main/resources/logback-spring.xml

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds">
+
+    <!-- 日志目录,可通过 logging.file.path 或环境变量 LOG_PATH 覆盖 -->
+    <springProperty scope="context" name="LOG_PATH" source="logging.file.path" defaultValue="logs"/>
+    <!-- 单文件大小上限,建议 200MB~500MB -->
+    <springProperty scope="context" name="MAX_FILE_SIZE" source="logging.logback.rollingpolicy.max-file-size" defaultValue="300MB"/>
+    <!-- 保留天数 -->
+    <springProperty scope="context" name="MAX_HISTORY" source="logging.logback.rollingpolicy.max-history" defaultValue="60"/>
+    <!-- 所有归档日志总大小上限 -->
+    <springProperty scope="context" name="TOTAL_SIZE_CAP" source="logging.logback.rollingpolicy.total-size-cap" defaultValue="20GB"/>
+
+    <property name="APP_NAME" value="fs-admin"/>
+    <property name="LOG_CHARSET" value="UTF-8"/>
+    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
+
+    <!-- 控制台(UTF-8,配合 -Dfile.encoding=UTF-8 与 LANG=zh_CN.UTF-8) -->
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <immediateFlush>true</immediateFlush>
+        </encoder>
+    </appender>
+
+    <!--
+        按「日期 + 大小」滚动,归档为 UTF-8 文本再 gzip:
+        - 每天凌晨跨日自动切割(fileNamePattern 含 yyyy-MM-dd)
+        - 单文件超过 MAX_FILE_SIZE 时在同一天内继续切割(.%i)
+    -->
+    <appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}/${APP_NAME}.log</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <immediateFlush>true</immediateFlush>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_PATH}/archive/${APP_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
+            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+            <totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
+            <cleanHistoryOnStart>false</cleanHistoryOnStart>
+        </rollingPolicy>
+    </appender>
+
+    <!-- ERROR 单独归档(UTF-8) -->
+    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}/${APP_NAME}-error.log</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>${LOG_CHARSET}</charset>
+            <immediateFlush>true</immediateFlush>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_PATH}/archive/${APP_NAME}-error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
+            <maxFileSize>${MAX_FILE_SIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+            <totalSizeCap>${TOTAL_SIZE_CAP}</totalSizeCap>
+        </rollingPolicy>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE_ALL"/>
+        <appender-ref ref="FILE_ERROR"/>
+    </root>
+
+    <logger name="com.fs" level="WARN"/>
+    <logger name="org.springframework" level="WARN"/>
+
+</configuration>

+ 4 - 4
fs-api/src/main/resources/application-dev.yml

@@ -30,14 +30,14 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://10.0.0.6:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://10.0.0.3:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 初始连接数
             initialSize: 5
             # 最小连接池数量

+ 6 - 1
fs-common/src/main/java/com/fs/common/enums/DataSourceType.java

@@ -15,5 +15,10 @@ public enum DataSourceType
     /**
      * 从库
      */
-    SLAVE
+    SLAVE,
+
+    /**
+     * huyi数据源
+     */
+    HUYI
 }

+ 27 - 0
fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java

@@ -155,6 +155,33 @@ public class PhoneUtils {
         return phone;
     }
 
+    /**
+     * 11位明文搜索时生成密文,供 SQL 同时匹配明文与加密存储
+     */
+    public static String encryptPlainPhoneForSearch(String phone) {
+        if (!isPlainMobile11(phone)) {
+            return null;
+        }
+        return encryptPlainOrKeep(phone);
+    }
+
+    /**
+     * 点击查看完整手机号:11位明文直返,超长密文解密后返回
+     */
+    public static String resolvePhoneForView(String phone) {
+        if (StrUtil.isBlank(phone)) {
+            return phone;
+        }
+        if (isPlainMobile11(phone)) {
+            return phone;
+        }
+        if (isMaskedPhone(phone)) {
+            return phone;
+        }
+        String plain = tryDecryptToPlain(phone);
+        return StrUtil.isNotBlank(plain) ? plain : phone;
+    }
+
     /**
      * 无权限查看时:先解为明文再脱敏展示
      */

+ 2 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveOrderController.java

@@ -8,6 +8,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -154,7 +155,7 @@ public class LiveOrderController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser.getUser().getUserType().equals("00")){
             LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(id));
-            String userPhone = order.getUserPhone();
+            String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
             return R.ok().put("userPhone",userPhone);
         }
         return R.error("无权查看");

+ 10 - 0
fs-company/src/main/java/com/fs/core/config/DruidConfig.java

@@ -49,6 +49,15 @@ public class DruidConfig
         return druidProperties.dataSource(dataSource);
     }
 
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.huyi")
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.huyi", name = "enabled", havingValue = "true", matchIfMissing = true)
+    public DataSource huyiDataSource(DruidProperties druidProperties)
+    {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
     @Bean(name = "dynamicDataSource")
     @Primary
     public DynamicDataSource dataSource(DataSource masterDataSource)
@@ -56,6 +65,7 @@ public class DruidConfig
         Map<Object, Object> targetDataSources = new HashMap<>();
         targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
         setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+        setDataSource(targetDataSources, DataSourceType.HUYI.name(), "huyiDataSource");
         return new DynamicDataSource(masterDataSource, targetDataSources);
     }
     

+ 14 - 0
fs-company/src/main/java/com/fs/store/controller/FsStoreAfterSalesController.java

@@ -8,18 +8,21 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.ICompanyUserService;
 import com.fs.core.security.LoginUser;
 import com.fs.core.web.service.TokenService;
 import com.fs.store.domain.*;
+import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.service.*;
 import com.fs.store.vo.FsStoreAfterSalesVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -48,6 +51,8 @@ public class FsStoreAfterSalesController extends BaseController
     private ICompanyUserService companyUserService;
     @Autowired
     private ICompanyService companyService;
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
 
 
     /**
@@ -57,6 +62,15 @@ public class FsStoreAfterSalesController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(FsStoreAfterSales fsStoreAfterSales)
     {
+        if (fsStoreAfterSales.getHuYiUserId() != null) {
+            String unionId = fsStoreOrderMapper.selectUnionIdByHyUserId(fsStoreAfterSales.getHuYiUserId());
+            if (StringUtils.isEmpty(unionId)) {
+                return getDataTable(new ArrayList<>());
+            }
+
+            fsStoreAfterSales.setUnionId(unionId);
+        }
+
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         fsStoreAfterSales.setCompanyId(loginUser.getCompany().getCompanyId());
         startPage();

+ 18 - 3
fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -10,6 +10,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
@@ -23,6 +24,7 @@ import com.fs.store.dto.ExpressInfoDTO;
 import com.fs.store.dto.StoreOrderProductDTO;
 import com.fs.store.enums.OrderLogEnum;
 import com.fs.store.enums.ShipperCodeEnum;
+import com.fs.store.mapper.FsStoreOrderMapper;
 import com.fs.store.param.FsStoreOrderBindCustomerParam;
 import com.fs.store.param.FsStoreOrderCreateUserParam;
 import com.fs.store.param.FsStoreOrderFinishParam;
@@ -39,6 +41,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -70,6 +73,9 @@ public class FsStoreOrderController extends BaseController
     private TokenService tokenService;
     @Autowired
     private ICrmCustomerService crmCustomerService;
+    @Autowired
+    private FsStoreOrderMapper fsStoreOrderMapper;
+
     /**
      * 查询订单列表
      */
@@ -78,6 +84,15 @@ public class FsStoreOrderController extends BaseController
     @DataScope(deptAlias = "cu",userAlias = "cu")
     public TableDataInfo list(FsStoreOrderParam param)
     {
+        if (param.getHuYiUserId() != null) {
+            String unionId = fsStoreOrderMapper.selectUnionIdByHyUserId(param.getHuYiUserId());
+            if (StringUtils.isEmpty(unionId)) {
+                return getDataTable(new ArrayList<>());
+            }
+
+            param.setUnionId(unionId);
+        }
+
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         param.setCompanyId(loginUser.getCompany().getCompanyId());
         startPage();
@@ -189,10 +204,10 @@ public class FsStoreOrderController extends BaseController
     public R getInfo(@PathVariable("id") Long id)
     {
         FsStoreOrder order=fsStoreOrderService.selectFsStoreOrderById(id);
-        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
+        order.setUserPhone(PhoneUtils.normalizePhoneForDisplay(order.getUserPhone()));
         order.setUserAddress(ParseUtils.parseAddress(order.getUserAddress()));
         FsUser user=userService.selectFsUserById(order.getUserId());
-        user.setPhone(ParseUtils.parsePhone(user.getPhone()));
+        user.setPhone(PhoneUtils.normalizePhoneForDisplay(user.getPhone()));
         FsStoreOrderItem itemMap=new FsStoreOrderItem();
         itemMap.setOrderId(order.getId());
         List<FsStoreOrderItem> items=orderItemService.selectFsStoreOrderItemList(itemMap);
@@ -225,7 +240,7 @@ public class FsStoreOrderController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         if (loginUser.getUser().getUserType().equals("00")){
             FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
-            String userPhone = order.getUserPhone();
+            String userPhone = PhoneUtils.resolvePhoneForView(order.getUserPhone());
             return R.ok().put("userPhone",userPhone);
         }
         return R.error("无权查看");

+ 8 - 4
fs-company/src/main/resources/application-dev.yml

@@ -30,14 +30,18 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://10.0.0.6:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://10.0.0.3:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
+            huyi:
+                url: jdbc:mysql://1.14.207.209:8008/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
-                password: Ylrz_1q2w3e4r5t6y
+                password: X7k#9mPq$2LvR&5n
             # 初始连接数
             initialSize: 5
             # 最小连接池数量
@@ -88,4 +92,4 @@ rocketmq:
     consumer:
         group: common-group
         access-key: ak16b45v4p9n150d89395b3c # 替换为实际的 accessKey
-        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey
+        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey

+ 5 - 0
fs-company/src/main/resources/application-druid.yml

@@ -38,6 +38,11 @@ spring:
                 url:
                 username:
                 password:
+
+            huyi:
+                url: jdbc:mysql://1.14.207.209:8008/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                username: root
+                password: X7k#9mPq$2LvR&5n
             # 初始连接数
             initialSize: 5
             # 最小连接池数量

+ 5 - 5
fs-live-mq/src/main/resources/application-dev.yml

@@ -30,14 +30,14 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://cd-cdb-7f33sq06.sql.tencentcdb.com:20329/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://cd-cdb-7f33sq06.sql.tencentcdb.com:20329?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 初始连接数
             initialSize: 5
             # 最小连接池数量
@@ -87,4 +87,4 @@ rocketmq:
     consumer:
         group: common-group
         access-key: ak16b45v4p9n150d89395b3c # 替换为实际的 accessKey
-        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey
+        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey

+ 5 - 5
fs-live-socket/src/main/resources/application-dev.yml

@@ -30,15 +30,15 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://10.0.0.6:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 从库数据源
             slave:
                 enabled: true
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://10.0.0.3:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
             # 初始连接数
             initialSize: 5
             # 最小连接池数量
@@ -87,4 +87,4 @@ rocketmq:
     consumer:
         group: common-group
         access-key: ak16b45v4p9n150d89395b3c # 替换为实际的 accessKey
-        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey
+        secret-key: sk370fb48d869b152b # 替换为实际的 secretKey

+ 9 - 8
fs-service-system/src/main/java/com/fs/erp/service/impl/JSTErpOrderServiceImpl.java

@@ -256,26 +256,27 @@ public class JSTErpOrderServiceImpl implements IErpOrderService {
 
     @Override
     public ErpOrderQueryResponse getOrderLive(ErpOrderQueryRequert param) {
-        // 1. 构建查询请求DTO
         OrderQueryRequestDTO requestDTO = new OrderQueryRequestDTO();
-        requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
-
+        if (StringUtils.isNotEmpty(param.getCode())) {
+            requestDTO.setOIds(Collections.singletonList(Long.valueOf(param.getCode())));
+        } else {
+            requestDTO.setOIds(param.getO_ids());
+            requestDTO.setShopId(Integer.parseInt(param.getShop_id()));
+            requestDTO.setPageIndex(param.getPage_index());
+            requestDTO.setPageSize(param.getPage_size());
+        }
 
-        // 2. 调用ERP服务查询订单
         OrderQueryResponseDTO query = jstErpHttpService.query(requestDTO);
 
-        // 3. 构建响应对象
         ErpOrderQueryResponse response = new ErpOrderQueryResponse();
 
-        // 4. 设置基本响应信息
-
-        // 5. 转换订单数据
         if (query.getOrders() != null && !query.getOrders().isEmpty()) {
             List<ErpOrderQuery> erpOrders = query.getOrders().stream()
                     .map(this::convertToErpOrderQueryLive)
                     .collect(Collectors.toList());
 
             response.setOrders(erpOrders);
+            response.setHasNext(query.getHasNext());
         } else {
             response.setOrders(Collections.emptyList());
         }

+ 2 - 0
fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderMapper.java

@@ -136,6 +136,8 @@ public interface LiveOrderMapper {
 
     List<LiveOrder> selectFsOutDateOrder();
 
+    void updateUpdateTimeByExtendIds(@Param("batch") List<String> batch);
+
     @Select("SELECT * FROM live_order WHERE live_id= #{liveId}")
     List<LiveOrder> selectOrderByLiveId(@Param("liveId") Long liveId);
 

+ 2 - 0
fs-service-system/src/main/java/com/fs/live/service/ILiveOrderService.java

@@ -193,6 +193,8 @@ public interface ILiveOrderService {
 
     void deliveryOrder(String orderCode, String mailNo, String expressCode, String expressName);
 
+    void updateUpdateTimeByExtendIds(List<String> extendOrderIds);
+
     LiveOrderComputeDTO computedOrder(long l, LiveOrderComputedParam param);
 
     LiveOrder selectOrderIdByOrderCode(String platformCode);

+ 13 - 42
fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -79,6 +79,7 @@ import com.fs.store.service.*;
 import com.fs.store.service.channel.PaymentHandler;
 import com.fs.store.service.channel.PaymentHandlerHolder;
 import com.fs.store.service.channel.param.PayProcessContext;
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.vo.FsStoreProductActivityListVO;
 import com.fs.system.config.SnowflakeUtils;
 import com.fs.system.service.ISysConfigService;
@@ -983,6 +984,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     public List<LiveOrder> selectLiveOrderList(LiveOrderQueryVO liveOrder) {
         normalizeLiveOrderQueryPayRange(liveOrder);
+        OrderPhoneSearchHelper.prepare(liveOrder);
         List<LiveOrder> liveOrders = baseMapper.selectLiveOrderList(liveOrder);
         if (CollectionUtils.isEmpty(liveOrders)) {
             return liveOrders;
@@ -1019,6 +1021,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     public List<LiveOrder> selectLiveOrderListExport(LiveOrderQueryVO liveOrder) {
         normalizeLiveOrderQueryPayRange(liveOrder);
+        OrderPhoneSearchHelper.prepare(liveOrder);
         List<LiveOrder> liveOrders = baseMapper.selectLiveOrderList(liveOrder);
         if (CollectionUtils.isEmpty(liveOrders)) {
             return liveOrders;
@@ -1784,6 +1787,14 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         return baseMapper.selectDeliverPenddingData();
     }
 
+    @Override
+    public void updateUpdateTimeByExtendIds(List<String> extendOrderIds) {
+        if (CollectionUtils.isEmpty(extendOrderIds)) {
+            return;
+        }
+        baseMapper.updateUpdateTimeByExtendIds(extendOrderIds);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
     public void deliveryOrder(String orderCode, String deliveryId, String deliverCode, String deliverName) {
@@ -2527,48 +2538,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Override
     @Transactional
     public R syncExpress(Long id) {
-        LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(id));
-        String lastFourNumber = "";
-        if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliveryCode().equals(ShipperCodeEnum.ZTO.getValue())) {
-            lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
-        }
-
-
-        List<FsStoreDelivers> byOrderId = fsStoreDeliversMapper.findByOrderIdWithType(order.getOrderId(),1);
-        if (byOrderId.isEmpty()) {
-            return R.error("当前账号没有快递记录!");
-        }
-        String orderCode = order.getOrderCode();
-
-        for (FsStoreDelivers fsStoreDelivers : byOrderId) {
-            if (ObjectUtil.isNotEmpty(fsStoreDelivers.getDeliverId())) {
-
-                ExpressInfoDTO dto = null;
-                try {
-                    // 记录HTTP请求前的信息
-                    log.info("开始调用快递查询接口, 订单号: {}, 快递公司编码: {}, 快递单号: {}, 手机号后四位: {}",
-                            orderCode, fsStoreDelivers.getDeliverId(), fsStoreDelivers.getDeliverSn(), lastFourNumber);
-                    dto = expressService.getExpressInfo(orderCode,
-                            fsStoreDelivers.getDeliverSn(), fsStoreDelivers.getDeliverId(), lastFourNumber);
-                    // 假设expressService.getExpressInfo内部进行了HTTP请求,你需要在expressService内部打印更详细的日志
-                    // 这里只记录返回结果
-                    if (ObjectUtil.isNotNull(dto)) {
-                        log.info("快递查询接口调用成功, 订单号: {}, 快递状态: {}, 扩展状态: {}",
-                                orderCode, dto.getState(), dto.getStateEx());
-                        fsStoreDelivers.setStatus(Integer.valueOf(dto.getState()));
-                        fsStoreDelivers.setStateEx(Integer.valueOf(dto.getStateEx()));
-                    } else {
-                        log.warn("快递查询接口调用成功,但返回结果为空, 订单号: {}", orderCode);
-                    }
-                } catch (Exception e) {
-                    log.error("快递查询接口调用失败, 订单号: {}, 快递单号: {}, 错误信息: {}", orderCode, fsStoreDelivers.getDeliverSn(), e.getMessage(), e);
-                }
-            } else {
-                log.info("发货单信息中快递ID为空, 跳过处理, 发货单ID: {}", fsStoreDelivers.getId());
-            }
-        }
-        fsStoreDeliversMapper.updateBatch(byOrderId);
-
+        fsStoreDeliversService.syncDeliverInfo(id,1);
+        fsStoreDeliversService.finishOrder(id,1);
 //        FsStoreDelivers delivers = byOrderId.get(0);
 //
 //        ExpressInfoDTO dto = expressService.getExpressInfo(order.getOrderCode(), delivers.getDeliverSn(), delivers.getDeliverId(), lastFourNumber);

+ 3 - 0
fs-service-system/src/main/java/com/fs/live/vo/LiveOrderQueryVO.java

@@ -68,6 +68,9 @@ public class LiveOrderQueryVO extends BaseEntity {
     @Excel(name = "收货人电话")
     private String userPhone;
 
+    /** 搜索用收货手机号密文 */
+    private String userPhoneEncrypted;
+
 
     /** 详细地址 */
     @Excel(name = "详细地址")

+ 38 - 0
fs-service-system/src/main/java/com/fs/store/config/ShippingTemplateRedisConfig.java

@@ -0,0 +1,38 @@
+package com.fs.store.config;
+
+import com.fs.store.listener.ShippingTemplateRefreshListener;
+import com.fs.store.service.ShippingTemplateRefreshService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.listener.ChannelTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+
+/**
+ * 注册运费模板 Redis Pub/Sub 监听;若应用未定义 ListenerContainer 则自动创建
+ */
+@Configuration
+@ConditionalOnClass(RedisMessageListenerContainer.class)
+public class ShippingTemplateRedisConfig {
+
+    @Bean
+    @ConditionalOnMissingBean(RedisMessageListenerContainer.class)
+    public RedisMessageListenerContainer shippingTemplateRedisMessageListenerContainer(
+            RedisConnectionFactory redisConnectionFactory) {
+        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(redisConnectionFactory);
+        return container;
+    }
+
+    @Bean
+    public Object shippingTemplateRefreshListenerRegistration(
+            RedisMessageListenerContainer redisMessageListenerContainer,
+            ShippingTemplateRefreshListener shippingTemplateRefreshListener) {
+        redisMessageListenerContainer.addMessageListener(
+                shippingTemplateRefreshListener,
+                new ChannelTopic(ShippingTemplateRefreshService.CHANNEL));
+        return new Object();
+    }
+}

+ 19 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsStoreAfterSales.java

@@ -104,6 +104,25 @@ public class FsStoreAfterSales extends BaseEntity
     private Long deptId;
     private String consigneePhone;
 
+    private Long huYiUserId;
+    private String unionId;
+
+    public Long getHuYiUserId() {
+        return huYiUserId;
+    }
+
+    public void setHuYiUserId(Long huYiUserId) {
+        this.huYiUserId = huYiUserId;
+    }
+
+    public String getUnionId() {
+        return unionId;
+    }
+
+    public void setUnionId(String unionId) {
+        this.unionId = unionId;
+    }
+
     /** 开始时间 */
     @JsonIgnore
     private String beginTime;

+ 32 - 0
fs-service-system/src/main/java/com/fs/store/listener/ShippingTemplateRefreshListener.java

@@ -0,0 +1,32 @@
+package com.fs.store.listener;
+
+import com.fs.store.service.ShippingTemplateRefreshService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 订阅运费模板变更广播,同步失效各实例本地内存
+ */
+@Slf4j
+@Component
+public class ShippingTemplateRefreshListener implements MessageListener {
+
+    @Autowired
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
+    @Override
+    public void onMessage(Message message, byte[] pattern) {
+        if (message == null || message.getBody() == null) {
+            return;
+        }
+        try {
+            Long templateId = Long.valueOf(new String(message.getBody()));
+            shippingTemplateRefreshService.invalidateLocal(templateId);
+        } catch (NumberFormatException e) {
+            log.warn("运费模板变更广播消息格式错误: {}", new String(message.getBody()));
+        }
+    }
+}

+ 16 - 4
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderItemMapper.java

@@ -92,10 +92,16 @@ public interface FsStoreOrderItemMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -164,13 +170,19 @@ public interface FsStoreOrderItemMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.realName != null and  maps.realName !=\"\"     '> " +
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +

+ 61 - 14
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreOrderMapper.java

@@ -6,6 +6,8 @@ import java.util.Map;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.api.param.OrderListParam;
 import com.fs.api.vo.OrderListVO;
+import com.fs.common.annotation.DataSource;
+import com.fs.common.enums.DataSourceType;
 import com.fs.company.param.CompanyStatisticsParam;
 import com.fs.company.vo.CompanySmsLogsStatisticsVO;
 import com.fs.company.vo.CompanyTuiMoneyStatisticsVO;
@@ -120,10 +122,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -232,10 +240,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -342,10 +356,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -622,10 +642,16 @@ public interface FsStoreOrderMapper
             "and o.real_name like CONCAT('%',#{maps.realName},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -727,10 +753,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -820,10 +852,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -879,10 +917,16 @@ public interface FsStoreOrderMapper
             "and u.nickname like CONCAT('%',#{maps.nickname},'%') " +
             "</if>" +
             "<if test = 'maps.phone != null and  maps.phone !=\"\"     '> " +
-            "and u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "and (u.phone like CONCAT('%',#{maps.phone},'%') " +
+            "<if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted !=\"\"'> " +
+            "or u.phone like CONCAT('%',#{maps.phoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.userPhone != null and  maps.userPhone !=\"\"     '> " +
-            "and o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "and (o.user_phone like CONCAT('%',#{maps.userPhone},'%') " +
+            "<if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted !=\"\"'> " +
+            "or o.user_phone like CONCAT('%',#{maps.userPhoneEncrypted},'%') " +
+            "</if>) " +
             "</if>" +
             "<if test = 'maps.status != null    '> " +
             "and o.status =#{maps.status} " +
@@ -1088,4 +1132,7 @@ public interface FsStoreOrderMapper
     List<FsStoreOrder> selectBankOrder();
 
     void updateUpdateTimeByExtendIds(@Param("batch") List<String> batch);
+
+    @DataSource(DataSourceType.HUYI)
+    String selectUnionIdByHyUserId(Long huYiUserId);
 }

+ 9 - 0
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderParam.java

@@ -15,8 +15,14 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
 
     private String phone;
 
+    /** 搜索用手机号密文(11位明文自动加密,匹配库中加密存储) */
+    private String phoneEncrypted;
+
     private String userPhone;
 
+    /** 搜索用收货手机号密文 */
+    private String userPhoneEncrypted;
+
     private Integer status;
 
     private Long companyId;
@@ -90,4 +96,7 @@ public class FsStoreOrderParam extends BaseEntity implements Serializable
 
     private String orderVisit;
 
+    private Long huYiUserId;
+    private String unionId;
+
 }

+ 77 - 0
fs-service-system/src/main/java/com/fs/store/service/ShippingTemplateRefreshService.java

@@ -0,0 +1,77 @@
+package com.fs.store.service;
+
+import com.fs.store.strategy.ShippingTemplateManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * 运费模板变更后统一刷新:Redis 计算缓存、本地内存、多实例广播
+ */
+@Slf4j
+@Service
+public class ShippingTemplateRefreshService {
+
+    public static final String CHANNEL = "shipping:template:changed";
+
+    @Autowired
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Autowired
+    private ShippingTemplateManager shippingTemplateManager;
+
+    public void refresh(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        clearShippingTemplateCache(templateId);
+        shippingTemplateManager.invalidate(templateId);
+        publish(templateId);
+        log.info("运费模板已刷新 templateId={}", templateId);
+    }
+
+    public void remove(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        clearShippingTemplateCache(templateId);
+        shippingTemplateManager.remove(templateId);
+        publish(templateId);
+        log.info("运费模板已删除缓存 templateId={}", templateId);
+    }
+
+    public void invalidateLocal(Long templateId) {
+        if (templateId == null) {
+            return;
+        }
+        shippingTemplateManager.invalidate(templateId);
+        log.info("收到运费模板变更广播,已失效本地缓存 templateId={}", templateId);
+    }
+
+    private void publish(Long templateId) {
+        try {
+            stringRedisTemplate.convertAndSend(CHANNEL, templateId.toString());
+        } catch (Exception e) {
+            log.error("广播运费模板变更失败 templateId={}", templateId, e);
+        }
+    }
+
+    /**
+     * 清理直播/下单运费 Redis 缓存,key:shipping:template:{templateId}:city:*
+     */
+    public void clearShippingTemplateCache(Long templateId) {
+        try {
+            String cacheKeyPattern = String.format("shipping:template:%s:city:*", templateId);
+            Set<String> keys = stringRedisTemplate.keys(cacheKeyPattern);
+            if (keys != null && !keys.isEmpty()) {
+                stringRedisTemplate.delete(keys);
+                log.info("清理运费模板 Redis 缓存成功 templateId={}, count={}", templateId, keys.size());
+            }
+        } catch (Exception e) {
+            log.error("清理运费模板 Redis 缓存失败 templateId={}", templateId, e);
+        }
+    }
+}

+ 31 - 3
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesFreeServiceImpl.java

@@ -6,10 +6,12 @@ import java.util.List;
 import com.fs.store.dto.TemplateDTO;
 import com.fs.store.strategy.FreeShippingRule;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesFreeMapper;
 import com.fs.store.domain.FsShippingTemplatesFree;
 import com.fs.store.service.IFsShippingTemplatesFreeService;
+import com.fs.store.service.ShippingTemplateRefreshService;
 
 /**
  * 免邮费Service业务层处理
@@ -23,6 +25,10 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Autowired
     private FsShippingTemplatesFreeMapper fsShippingTemplatesFreeMapper;
 
+    @Autowired
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
     /**
      * 查询免邮费
      *
@@ -56,7 +62,9 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int insertFsShippingTemplatesFree(FsShippingTemplatesFree fsShippingTemplatesFree)
     {
-        return fsShippingTemplatesFreeMapper.insertFsShippingTemplatesFree(fsShippingTemplatesFree);
+        int result = fsShippingTemplatesFreeMapper.insertFsShippingTemplatesFree(fsShippingTemplatesFree);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesFree.getTempId());
+        return result;
     }
 
     /**
@@ -68,7 +76,9 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int updateFsShippingTemplatesFree(FsShippingTemplatesFree fsShippingTemplatesFree)
     {
-        return fsShippingTemplatesFreeMapper.updateFsShippingTemplatesFree(fsShippingTemplatesFree);
+        int result = fsShippingTemplatesFreeMapper.updateFsShippingTemplatesFree(fsShippingTemplatesFree);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesFree.getTempId());
+        return result;
     }
 
     /**
@@ -80,6 +90,7 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int deleteFsShippingTemplatesFreeByIds(Long[] ids)
     {
+        refreshByFreeIds(ids);
         return fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeByIds(ids);
     }
 
@@ -92,7 +103,24 @@ public class FsShippingTemplatesFreeServiceImpl implements IFsShippingTemplatesF
     @Override
     public int deleteFsShippingTemplatesFreeById(Long id)
     {
-        return fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeById(id);
+        FsShippingTemplatesFree free = fsShippingTemplatesFreeMapper.selectFsShippingTemplatesFreeById(id);
+        int result = fsShippingTemplatesFreeMapper.deleteFsShippingTemplatesFreeById(id);
+        if (free != null) {
+            shippingTemplateRefreshService.refresh(free.getTempId());
+        }
+        return result;
+    }
+
+    private void refreshByFreeIds(Long[] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (Long id : ids) {
+            FsShippingTemplatesFree free = fsShippingTemplatesFreeMapper.selectFsShippingTemplatesFreeById(id);
+            if (free != null) {
+                shippingTemplateRefreshService.refresh(free.getTempId());
+            }
+        }
     }
 
     @Override

+ 31 - 3
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesRegionServiceImpl.java

@@ -3,10 +3,12 @@ package com.fs.store.service.impl;
 import java.util.Collections;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesRegionMapper;
 import com.fs.store.domain.FsShippingTemplatesRegion;
 import com.fs.store.service.IFsShippingTemplatesRegionService;
+import com.fs.store.service.ShippingTemplateRefreshService;
 
 /**
  * 邮费区域Service业务层处理
@@ -20,6 +22,10 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Autowired
     private FsShippingTemplatesRegionMapper fsShippingTemplatesRegionMapper;
 
+    @Autowired
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
+
     /**
      * 查询邮费区域
      *
@@ -53,7 +59,9 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int insertFsShippingTemplatesRegion(FsShippingTemplatesRegion fsShippingTemplatesRegion)
     {
-        return fsShippingTemplatesRegionMapper.insertFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        int result = fsShippingTemplatesRegionMapper.insertFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesRegion.getTempId());
+        return result;
     }
 
     /**
@@ -65,7 +73,9 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int updateFsShippingTemplatesRegion(FsShippingTemplatesRegion fsShippingTemplatesRegion)
     {
-        return fsShippingTemplatesRegionMapper.updateFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        int result = fsShippingTemplatesRegionMapper.updateFsShippingTemplatesRegion(fsShippingTemplatesRegion);
+        shippingTemplateRefreshService.refresh(fsShippingTemplatesRegion.getTempId());
+        return result;
     }
 
     /**
@@ -77,6 +87,7 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int deleteFsShippingTemplatesRegionByIds(Long[] ids)
     {
+        refreshByRegionIds(ids);
         return fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionByIds(ids);
     }
 
@@ -89,7 +100,24 @@ public class FsShippingTemplatesRegionServiceImpl implements IFsShippingTemplate
     @Override
     public int deleteFsShippingTemplatesRegionById(Long id)
     {
-        return fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionById(id);
+        FsShippingTemplatesRegion region = fsShippingTemplatesRegionMapper.selectFsShippingTemplatesRegionById(id);
+        int result = fsShippingTemplatesRegionMapper.deleteFsShippingTemplatesRegionById(id);
+        if (region != null) {
+            shippingTemplateRefreshService.refresh(region.getTempId());
+        }
+        return result;
+    }
+
+    private void refreshByRegionIds(Long[] ids) {
+        if (ids == null) {
+            return;
+        }
+        for (Long id : ids) {
+            FsShippingTemplatesRegion region = fsShippingTemplatesRegionMapper.selectFsShippingTemplatesRegionById(id);
+            if (region != null) {
+                shippingTemplateRefreshService.refresh(region.getTempId());
+            }
+        }
     }
 
     @Override

+ 8 - 45
fs-service-system/src/main/java/com/fs/store/service/impl/FsShippingTemplatesServiceImpl.java

@@ -2,7 +2,6 @@ package com.fs.store.service.impl;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
 import cn.hutool.core.bean.BeanUtil;
@@ -19,9 +18,10 @@ import com.fs.store.dto.RegionInfoDTO;
 import com.fs.store.mapper.FsShippingTemplatesFreeMapper;
 import com.fs.store.mapper.FsShippingTemplatesRegionMapper;
 import com.fs.store.param.FsShippingTemplatesAddEditParam;
+import com.fs.store.service.ShippingTemplateRefreshService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsShippingTemplatesMapper;
 import com.fs.store.domain.FsShippingTemplates;
@@ -29,7 +29,6 @@ import com.fs.store.service.IFsShippingTemplatesService;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import lombok.extern.slf4j.Slf4j;
-import java.util.Set;
 
 /**
  * 运费模板Service业务层处理
@@ -51,9 +50,8 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     private FsShippingTemplatesRegionMapper fsShippingTemplatesRegionMapper;
 
     @Autowired
-    private StringRedisTemplate stringRedisTemplate;
-
-
+    @Lazy
+    private ShippingTemplateRefreshService shippingTemplateRefreshService;
 
     /**
      * 查询运费模板
@@ -102,12 +100,7 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int updateFsShippingTemplates(FsShippingTemplates fsShippingTemplates)
     {
         fsShippingTemplates.setUpdateTime(DateUtils.getNowDate());
-        int result = fsShippingTemplatesMapper.updateFsShippingTemplates(fsShippingTemplates);
-        // 清理相关缓存
-        if (fsShippingTemplates.getId() != null) {
-            clearShippingTemplateCache(fsShippingTemplates.getId());
-        }
-        return result;
+        return fsShippingTemplatesMapper.updateFsShippingTemplates(fsShippingTemplates);
     }
 
     /**
@@ -120,10 +113,9 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int deleteFsShippingTemplatesByIds(Long[] ids)
     {
         int result = fsShippingTemplatesMapper.deleteFsShippingTemplatesByIds(ids);
-        // 清理相关缓存
         if (ids != null && ids.length > 0) {
             for (Long id : ids) {
-                clearShippingTemplateCache(id);
+                shippingTemplateRefreshService.remove(id);
             }
         }
         return result;
@@ -139,9 +131,8 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
     public int deleteFsShippingTemplatesById(Long ids)
     {
         int result = fsShippingTemplatesMapper.deleteFsShippingTemplatesById(ids);
-        // 清理相关缓存
         if (ids != null) {
-            clearShippingTemplateCache(ids);
+            shippingTemplateRefreshService.remove(ids);
         }
         return result;
     }
@@ -158,7 +149,6 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
         shippingTemplates.setAppointInfo(JSON.toJSONString(fsShippingTemplates.getAppointInfo()));
         if(fsShippingTemplates.getId() != null && fsShippingTemplates.getId()  > 0){
             shippingTemplates.setId(fsShippingTemplates.getId());
-            // updateFsShippingTemplates 方法内部已经会清理缓存
             this.updateFsShippingTemplates(shippingTemplates);
         }else{
             shippingTemplates.setCreateTime(DateUtils.getNowDate());
@@ -167,6 +157,7 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
 
         this.saveRegion(fsShippingTemplates,shippingTemplates.getId());
         this.saveFreeReigion(fsShippingTemplates,shippingTemplates.getId());
+        shippingTemplateRefreshService.refresh(shippingTemplates.getId());
         return R.ok();
     }
 
@@ -191,7 +182,6 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
         List<FsShippingTemplatesRegion> fsShippingTemplatesRegions = new ArrayList<>();
 
         for (RegionInfoDTO regionInfoDto : regionInfo){
-            String uni = IdUtil.simpleUUID();
             if(regionInfoDto.getRegion() != null && !regionInfoDto.getRegion().isEmpty()){
                 for (RegionDTO regionDto : regionInfoDto.getRegion()){
                     if(regionDto.getChildren() != null && !regionDto.getChildren().isEmpty()){
@@ -265,31 +255,4 @@ public class FsShippingTemplatesServiceImpl implements IFsShippingTemplatesServi
             fsShippingTemplatesFreeMapper.saveBatch(shippingTemplatesFreeList);
         }
     }
-
-    /**
-     * 清理运费模板相关的缓存
-     * 缓存key格式:shipping:template:{templateId}:city:{cityIds}
-     * 
-     * @param templateId 运费模板ID
-     */
-    private void clearShippingTemplateCache(Long templateId) {
-        try {
-            if (templateId == null) {
-                return;
-            }
-            // 构建缓存key前缀:shipping:template:{templateId}:city:*
-            String cacheKeyPattern = String.format("shipping:template:%s:city:*", templateId);
-            // 查找所有匹配的缓存key
-            Set<String> keys = stringRedisTemplate.keys(cacheKeyPattern);
-            if (keys != null && !keys.isEmpty()) {
-                // 批量删除匹配的缓存
-                stringRedisTemplate.delete(keys);
-                log.info("清理运费模板缓存成功,templateId: {}, 删除缓存数量: {}", templateId, keys.size());
-            } else {
-                log.debug("未找到需要清理的运费模板缓存,templateId: {}", templateId);
-            }
-        } catch (Exception e) {
-            log.error("清理运费模板缓存失败,templateId: {}", templateId, e);
-        }
-    }
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderItemServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.store.service.impl;
 
 import java.util.List;
 
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.param.FsStoreOrderParam;
 import com.fs.store.vo.FsStoreOrderItemExportVO;
 import com.fs.store.vo.FsStoreOrderItemVO;
@@ -102,11 +103,13 @@ public class FsStoreOrderItemServiceImpl implements IFsStoreOrderItemService
 
     @Override
     public List<FsStoreOrderItemExportVO> selectFsStoreOrderItemListExportVO(FsStoreOrderParam fsStoreOrder) {
+        OrderPhoneSearchHelper.prepare(fsStoreOrder);
         return fsStoreOrderItemMapper.selectFsStoreOrderItemListExportVO(fsStoreOrder);
     }
 
     @Override
     public Long countFsStoreOrderItemListExportVO(FsStoreOrderParam fsStoreOrder) {
+        OrderPhoneSearchHelper.prepare(fsStoreOrder);
         return fsStoreOrderItemMapper.itemsCount(fsStoreOrder);
     }
 

+ 18 - 9
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -92,6 +92,7 @@ import com.fs.store.service.channel.PaymentHandlerHolder;
 import com.fs.store.service.channel.param.PayProcessContext;
 import com.fs.store.strategy.ShippingOrder;
 import com.fs.store.strategy.ShippingTemplateManager;
+import com.fs.store.util.OrderPhoneSearchHelper;
 import com.fs.store.vo.*;
 import com.fs.system.config.SnowflakeUtils;
 import com.fs.system.service.ISysConfigService;
@@ -565,6 +566,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsStoreOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -582,6 +584,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsStoreOrderAllListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderAllListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -599,6 +602,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectPayRemainListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsPayRemainListVO(param);
         for(FsStoreOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -618,6 +622,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsPromotionOrderVO> selectFsPromotionOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsPromotionOrderVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVO(param);
         for(FsPromotionOrderVO vo:list){
             String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
@@ -1250,15 +1255,15 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
             fsWxExpressTaskMapper.insert(fsWxExpressTask);
 
             // 微信消息通知
-            TemplateBean templateBean = TemplateBean.builder()
-                    .orderId(order.getId().toString())
-                    .orderCode(order.getOrderCode())
-                    .deliveryId(deliveryId)
-                    .deliveryName(express.getName())
-                    .userId(order.getUserId())
-                    .templateType(TemplateListenEnum.TYPE_2.getValue())
-                    .build();
-            publisher.publishEvent(new TemplateEvent(this, templateBean));
+//            TemplateBean templateBean = TemplateBean.builder()
+//                    .orderId(order.getId().toString())
+//                    .orderCode(order.getOrderCode())
+//                    .deliveryId(deliveryId)
+//                    .deliveryName(express.getName())
+//                    .userId(order.getUserId())
+//                    .templateType(TemplateListenEnum.TYPE_2.getValue())
+//                    .build();
+//            publisher.publishEvent(new TemplateEvent(this, templateBean));
 
         }
     }
@@ -2883,6 +2888,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderExportVO> selectFsStoreOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderExportVO> fsStoreOrderExportVOS = fsStoreOrderMapper.selectFsStoreOrderListVOByExport(param);
         Map<Long, FsStorePayment> paymentMap = fsStorePaymentMapper.selectAllPayments();
         for (FsStoreOrderExportVO item : fsStoreOrderExportVOS) {
@@ -2896,6 +2902,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderPromotionExportVO> selectFsPromotionOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         List<FsStoreOrderPromotionExportVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVOByExport(param);
         for (FsStoreOrderPromotionExportVO vo : list){
            FsStoreOrderBrokerageVO brokerageVO = fsStoreOrderMapper.selectBrokerage(vo.getId());
@@ -2908,6 +2915,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStorePayRemainOrderExportVO> selectFsStorePayRemainOrderListVOByExport(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         return fsStoreOrderMapper.selectFsStorePayRemainOrderListVOByExport(param);
     }
 
@@ -2918,6 +2926,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Override
     public List<FsStoreOrderVO> selectFsCustomerStoreOrderListVO(FsStoreOrderParam param) {
+        OrderPhoneSearchHelper.prepare(param);
         return fsStoreOrderMapper.selectFsCustomerStoreOrderListVO(param);
     }
 

+ 88 - 75
fs-service-system/src/main/java/com/fs/store/strategy/ShippingTemplateManager.java

@@ -8,121 +8,134 @@ import com.fs.store.enums.ShippingTempEnum;
 import com.fs.store.service.IFsShippingTemplatesFreeService;
 import com.fs.store.service.IFsShippingTemplatesRegionService;
 import com.fs.store.service.IFsShippingTemplatesService;
-import com.fs.store.strategy.impl.CountBasedStrategy;
-import com.fs.store.strategy.impl.WeightBasedStrategy;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.ObjectUtils;
 import org.apache.http.util.Asserts;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * 运费模板管理器
+ * 运费模板管理器(懒加载,变更后 invalidate 即可热更新)
  */
 @Slf4j
 @Service
 public class ShippingTemplateManager {
     @Autowired
+    @Lazy
     private IFsShippingTemplatesService fsShippingTemplatesService;
     @Autowired
+    @Lazy
     private IFsShippingTemplatesRegionService fsShippingTemplatesRegionService;
     @Autowired
+    @Lazy
     private IFsShippingTemplatesFreeService fsShippingTemplatesFreeService;
 
     private final Map<Long, ShippingTemplate> TEMPLATES = new ConcurrentHashMap<>();
 
     private static final Map<Integer, String> TEMPLATE_TYPE_MAP = new ConcurrentHashMap<>();
     static {
-        TEMPLATE_TYPE_MAP.put(1,"count");
-        TEMPLATE_TYPE_MAP.put(2,"weight");
-        TEMPLATE_TYPE_MAP.put(3,"volume");
+        TEMPLATE_TYPE_MAP.put(1, "count");
+        TEMPLATE_TYPE_MAP.put(2, "weight");
+        TEMPLATE_TYPE_MAP.put(3, "volume");
     }
 
-    @PostConstruct
-    public void init(){
-        log.info("正在初始化运费模板管理器...");
-        // 查询运费模板
-        List<FsShippingTemplates> fsShippingTemplates = fsShippingTemplatesService.listAllTemplate();
-        for (FsShippingTemplates template : fsShippingTemplates) {
-            String type = TEMPLATE_TYPE_MAP.get(template.getType());
-            Asserts.notNull(type,"不支持的模板类型");
-
-            ShippingTemplate shippingTemplate = new ShippingTemplate(template.getId(),type);
-
-            log.info("正在加载模板配送区域及运费");
-            List<FsShippingTemplatesRegion> fsShippingTemplatesRegions = fsShippingTemplatesRegionService.selectTempRegionByTempIdAndCityId(template.getId());
-            for (FsShippingTemplatesRegion templatesRegion : fsShippingTemplatesRegions) {
-                Region region = new Region();
-                region.setCityId(templatesRegion.getCityId());
-                // 如果是按重量
-                if(ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_2.getValue())){
-                    region.setFirstWeight(templatesRegion.getFirst());
-                    region.setFirstWeightFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalWeight(templatesRegion.getContinues());
-                    region.setAdditionalWeightFee(templatesRegion.getContinuePrice());
-                } else if(ObjectUtil.equal(templatesRegion.getType(),ShippingTempEnum.TYPE_1.getValue())){
-                    region.setFirstItem(templatesRegion.getFirst());
-                    region.setFirstItemFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalItemFee(templatesRegion.getContinuePrice());
-                } else if(ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_3.getValue())){
-                    region.setFirstVolume(templatesRegion.getFirst());
-                    region.setFirstVolumeFee(templatesRegion.getFirstPrice());
-                    region.setAdditionalVolume(templatesRegion.getContinues());
-                    region.setAdditionalVolumeFee(templatesRegion.getContinuePrice());
-                }
-                shippingTemplate.addRegion(region);
-            }
-
-
-            log.info("模板加载区域完成: {}个", fsShippingTemplatesRegions.size());
-
-            log.info("正在加载模板包邮规则");
-            List<FsShippingTemplatesFree> freeShippingRules = fsShippingTemplatesFreeService.selectFreeShippingRuleByTempId(template.getId());
-            for (FsShippingTemplatesFree freeShippingRule : freeShippingRules) {
-                FreeShippingRule rule = new FreeShippingRule();
-                rule.setRegion(freeShippingRule.getCityId());
-
-                if(ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_2.getValue())){
-                    rule.setMinWeight(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                } else if(ObjectUtil.equal(freeShippingRule.getType(),ShippingTempEnum.TYPE_1.getValue())){
-                    rule.setMinCount(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                } else if(ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_3.getValue())){
-                    rule.setMinVolume(freeShippingRule.getNumber());
-                    rule.setMinAmount(freeShippingRule.getPrice());
-                }
-
-                shippingTemplate.addFreeShippingRule(rule);
-            }
-            log.info("模板包邮规则加载完成: {} 个", freeShippingRules);
-
-            this.addTemplate(shippingTemplate);
+    public void invalidate(Long templateId) {
+        if (templateId != null) {
+            TEMPLATES.remove(templateId);
         }
-        log.info("运费模板管理器初始化完成: {}个", fsShippingTemplates.size());
     }
 
-    public void addTemplate(ShippingTemplate template) {
-        TEMPLATES.put(template.getId(), template);
+    public void remove(Long templateId) {
+        invalidate(templateId);
+    }
+
+    public void reload(Long templateId) {
+        invalidate(templateId);
+        getTemplate(templateId);
     }
 
     public ShippingTemplate getTemplate(Long templateId) {
-        return TEMPLATES.get(templateId);
+        if (templateId == null) {
+            return null;
+        }
+        ShippingTemplate cached = TEMPLATES.get(templateId);
+        if (cached != null) {
+            return cached;
+        }
+        ShippingTemplate loaded = buildTemplateFromDb(templateId);
+        if (loaded != null) {
+            TEMPLATES.put(templateId, loaded);
+        }
+        return loaded;
     }
 
     public BigDecimal calculateShippingFee(Long templateId, ShippingOrder order) {
-        ShippingTemplate template = TEMPLATES.get(templateId);
+        ShippingTemplate template = getTemplate(templateId);
         if (template == null) {
             throw new IllegalArgumentException("找不到运费模板: " + templateId);
         }
         return template.calculateShippingFee(order);
     }
-}
 
+    private ShippingTemplate buildTemplateFromDb(Long templateId) {
+        FsShippingTemplates template = fsShippingTemplatesService.selectFsShippingTemplatesById(templateId);
+        if (template == null || ObjectUtil.equal(template.getIsDel(), 1)) {
+            log.warn("运费模板不存在或已删除 templateId={}", templateId);
+            return null;
+        }
+        String type = TEMPLATE_TYPE_MAP.get(template.getType());
+        Asserts.notNull(type, "不支持的模板类型");
+
+        ShippingTemplate shippingTemplate = new ShippingTemplate(template.getId(), type);
+
+        List<FsShippingTemplatesRegion> regions =
+                fsShippingTemplatesRegionService.selectTempRegionByTempIdAndCityId(template.getId());
+        for (FsShippingTemplatesRegion templatesRegion : regions) {
+            Region region = new Region();
+            region.setCityId(templatesRegion.getCityId());
+            if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_2.getValue())) {
+                region.setFirstWeight(templatesRegion.getFirst());
+                region.setFirstWeightFee(templatesRegion.getFirstPrice());
+                region.setAdditionalWeight(templatesRegion.getContinues());
+                region.setAdditionalWeightFee(templatesRegion.getContinuePrice());
+            } else if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_1.getValue())) {
+                region.setFirstItem(templatesRegion.getFirst());
+                region.setFirstItemFee(templatesRegion.getFirstPrice());
+                region.setAdditionalItemFee(templatesRegion.getContinuePrice());
+            } else if (ObjectUtil.equal(templatesRegion.getType(), ShippingTempEnum.TYPE_3.getValue())) {
+                region.setFirstVolume(templatesRegion.getFirst());
+                region.setFirstVolumeFee(templatesRegion.getFirstPrice());
+                region.setAdditionalVolume(templatesRegion.getContinues());
+                region.setAdditionalVolumeFee(templatesRegion.getContinuePrice());
+            }
+            shippingTemplate.addRegion(region);
+        }
+
+        List<FsShippingTemplatesFree> freeShippingRules =
+                fsShippingTemplatesFreeService.selectFreeShippingRuleByTempId(template.getId());
+        for (FsShippingTemplatesFree freeShippingRule : freeShippingRules) {
+            FreeShippingRule rule = new FreeShippingRule();
+            rule.setRegion(freeShippingRule.getCityId());
+            if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_2.getValue())) {
+                rule.setMinWeight(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            } else if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_1.getValue())) {
+                rule.setMinCount(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            } else if (ObjectUtil.equal(freeShippingRule.getType(), ShippingTempEnum.TYPE_3.getValue())) {
+                rule.setMinVolume(freeShippingRule.getNumber());
+                rule.setMinAmount(freeShippingRule.getPrice());
+            }
+            shippingTemplate.addFreeShippingRule(rule);
+        }
+
+        log.debug("懒加载运费模板 templateId={}, regions={}, freeRules={}",
+                templateId, regions.size(), freeShippingRules.size());
+        return shippingTemplate;
+    }
+}

+ 43 - 0
fs-service-system/src/main/java/com/fs/store/util/OrderPhoneSearchHelper.java

@@ -0,0 +1,43 @@
+package com.fs.store.util;
+
+import cn.hutool.core.util.StrUtil;
+import com.fs.common.utils.PhoneUtils;
+import com.fs.live.vo.LiveOrderQueryVO;
+import com.fs.store.param.FsStoreOrderParam;
+
+/**
+ * 订单手机号搜索:11位明文同时匹配库中明文与密文
+ */
+public final class OrderPhoneSearchHelper {
+
+    private OrderPhoneSearchHelper() {
+    }
+
+    public static void prepare(FsStoreOrderParam param) {
+        if (param == null) {
+            return;
+        }
+        if (StrUtil.isNotBlank(param.getUserPhone())) {
+            String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getUserPhone());
+            if (StrUtil.isNotBlank(encrypted)) {
+                param.setUserPhoneEncrypted(encrypted);
+            }
+        }
+        if (StrUtil.isNotBlank(param.getPhone())) {
+            String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getPhone());
+            if (StrUtil.isNotBlank(encrypted)) {
+                param.setPhoneEncrypted(encrypted);
+            }
+        }
+    }
+
+    public static void prepare(LiveOrderQueryVO param) {
+        if (param == null || StrUtil.isBlank(param.getUserPhone())) {
+            return;
+        }
+        String encrypted = PhoneUtils.encryptPlainPhoneForSearch(param.getUserPhone());
+        if (StrUtil.isNotBlank(encrypted)) {
+            param.setUserPhoneEncrypted(encrypted);
+        }
+    }
+}

+ 2 - 2
fs-service-system/src/main/resources/application-config.yml

@@ -128,8 +128,8 @@ snowflake:
 
 
 tencent_cloud_config:
-  secret_id: AKIDeJvMkz0oSt78OQGvNaZLtDKCrVvIi2HW
-  secret_key: 6ze6KMCrIXhdNuSu9BB3nW5QYSCsLZYJ
+  secret_id: AKIDGkFjFpVFxmbXVYedXO8j9SYcabacaavA
+  secret_key: BLPNDuUyKXfjeR6d3MZhjhaRI72CLTgk
   bucket: fs-1319721001
   app_id: 1319721001
   region: ap-chongqing

+ 14 - 1
fs-service-system/src/main/resources/mapper/live/LiveOrderMapper.xml

@@ -130,7 +130,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="appCompanyUserId != null"> and fu.app_company_user_id = #{appCompanyUserId}</if>
             <if test="appCompanyUserName != null and appCompanyUserName != ''"> and fu.app_company_user_name like concat('%', #{appCompanyUserName}, '%')</if>
             <if test="userName != null  and userName != ''"> and a.user_name like concat('%', #{userName}, '%')</if>
-            <if test="userPhone != null  and userPhone != ''"> and a.user_phone = #{userPhone}</if>
+            <if test="userPhone != null  and userPhone != ''">
+                and (a.user_phone like concat(#{userPhone},'%')
+                <if test="userPhoneEncrypted != null and userPhoneEncrypted != ''">
+                    or a.user_phone like concat(#{userPhoneEncrypted},'%')
+                </if>)
+            </if>
             <if test="userAddress != null  and userAddress != ''"> and a.user_address = #{userAddress}</if>
             <if test="cartId != null  and cartId != ''"> and cart_id = #{cartId}</if>
             <if test="totalNum != null  and totalNum != ''"> and total_num = #{totalNum}</if>
@@ -642,4 +647,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </select>
 
+    <update id="updateUpdateTimeByExtendIds">
+        UPDATE live_order SET update_time = NOW()
+        WHERE extend_order_id IN
+        <foreach item="item" collection="batch" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </update>
+
 </mapper>

+ 3 - 0
fs-service-system/src/main/resources/mapper/store/FsStoreAfterSalesMapper.xml

@@ -146,6 +146,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test = 'maps.deptId != null'>
                 AND (o.dept_id = #{maps.deptId} OR o.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{maps.deptId}, ancestors) ))
             </if>
+            <if test = 'maps.unionId != null and  maps.unionId != "" '>
+                AND u.union_id = #{maps.unionId}
+            </if>
             ${maps.params.dataScope}
         </where>
         order by s.create_time desc

+ 15 - 2
fs-service-system/src/main/resources/mapper/store/FsStoreOrderMapper.xml

@@ -610,10 +610,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 and o.real_name like CONCAT(#{maps.realName},'%')
             </if>
             <if test = 'maps.phone != null and  maps.phone !=""     '>
-                and u.phone like CONCAT(#{maps.phone},'%')
+                and (u.phone like CONCAT(#{maps.phone},'%')
+                <if test = 'maps.phoneEncrypted != null and maps.phoneEncrypted != ""'>
+                    or u.phone like CONCAT(#{maps.phoneEncrypted},'%')
+                </if>)
             </if>
             <if test = 'maps.userPhone != null and  maps.userPhone !=""     '>
-                and o.user_phone like CONCAT(#{maps.userPhone},'%')
+                and (o.user_phone like CONCAT(#{maps.userPhone},'%')
+                <if test = 'maps.userPhoneEncrypted != null and maps.userPhoneEncrypted != ""'>
+                    or o.user_phone like CONCAT(#{maps.userPhoneEncrypted},'%')
+                </if>)
             </if>
             <if test = 'maps.status != null    '>
                 and o.status =#{maps.status}
@@ -678,6 +684,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test = 'maps.deptId != null    '>
                 AND (o.dept_id = #{maps.deptId} OR o.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{maps.deptId}, ancestors) ))
             </if>
+            <if test = 'maps.unionId != null and  maps.unionId != "" '>
+                AND u.union_id = #{maps.unionId}
+            </if>
             ${maps.params.dataScope}
         </where>
         <if test = 'maps.productName != null and  maps.productName != "" '>
@@ -686,6 +695,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by o.id desc
     </select>
 
+    <select id="selectUnionIdByHyUserId" resultType="java.lang.String">
+        SELECT union_id unionId FROM `fs_user` WHERE user_id = #{huYiUserId}
+    </select>
+
     <update id="updateUpdateTimeByExtendIds">
         UPDATE fs_store_order SET update_time = NOW()
         WHERE extend_order_id IN

+ 4 - 4
fs-user-app/src/main/resources/application-dev.yml

@@ -30,8 +30,8 @@ spring:
             # 主库数据源
             master:
                 url: jdbc:mysql://10.0.0.6:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
                 # 初始连接数
                 initialSize: 100
                 # 最小连接池数量
@@ -45,8 +45,8 @@ spring:
                 enabled: true
                 # 从数据源开关/默认关闭
                 url: jdbc:mysql://10.0.0.3:3306/fs_ffhx_shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: root
-                password: Ylrz_1q2w3e4r5t6y
+                username: fhhxadmin
+                password: fhhx_1q0p2w9o3e8i
                 # 初始连接数
                 initialSize: 100
                 # 最小连接池数量