Selaa lähdekoodia

Merge branch 'master' into tys

沐梦. 13 tuntia sitten
vanhempi
sitoutus
dc775ed128
100 muutettua tiedostoa jossa 3156 lisäystä ja 558 poistoa
  1. 8 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerContactService.java
  2. 5 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java
  3. 13 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/dto/CustomerInfoDTO.java
  4. 6 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteExternalItemService.java
  5. 36 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyLogisticsCompanyDto.java
  6. 10 3
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/tongji/RemoteTongJiPullService.java
  7. 36 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/RemoteOrderInfoService.java
  8. 26 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/HotProductRankingDto.java
  9. 39 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/LatestOrderDto.java
  10. 27 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/OrderAmountTrendDto.java
  11. 131 0
      ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/PartnerOrderIndexDto.java
  12. 5 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductService.java
  13. 5 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/CategoryDto.java
  14. 11 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCurrencyService.java
  15. 11 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCustomerTypeService.java
  16. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComLogisticsCompanyService.java
  17. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComStaffService.java
  18. 2 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteErpStaffService.java
  19. 11 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteProductTaxrateService.java
  20. 8 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSupplierLevelService.java
  21. 7 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSupplierTypeService.java
  22. 27 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaxCodeService.java
  23. 7 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteSupplierTypeVo.java
  24. 85 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaxCodeVo.java
  25. 7 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/model/LoginUser.java
  26. 1 1
      ruoyi-auth/src/main/java/org/dromara/auth/controller/Auth2Controller.java
  27. 119 0
      ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SerialNumberStrategy.java
  28. 5 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java
  29. 1 1
      ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java
  30. 1 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/controller/pc/PcStatementProductController.java
  31. 4 0
      ruoyi-modules/ruoyi-customer/pom.xml
  32. 6 6
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/ContractSupplyController.java
  33. 28 8
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java
  34. 41 17
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/PartnerInfoController.java
  35. 10 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierInfoController.java
  36. 12 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcCustomerMessageController.java
  37. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerMessage.java
  38. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierQualification.java
  39. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerInfoBo.java
  40. 4 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerMessageBo.java
  41. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierQualificationBo.java
  42. 103 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerIndexDataVo.java
  43. 45 3
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerInfoImportVo.java
  44. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerMessageVo.java
  45. 136 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/PartnerInfoIndexDataVo.java
  46. 82 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/PartnerManageIndexDataVo.java
  47. 25 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoImportVo.java
  48. 6 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoVo.java
  49. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierQualificationVo.java
  50. 18 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerContactServiceImpl.java
  51. 4 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java
  52. 14 4
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteSupplierInfoServiceImpl.java
  53. 19 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/listener/CustomerImportListener.java
  54. 12 4
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/CustomerInfoMapper.java
  55. 9 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/TeamMemberMapper.java
  56. 10 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java
  57. 12 5
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java
  58. 8 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerMessageService.java
  59. 39 31
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/IPartnerInfoService.java
  60. 9 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierInfoService.java
  61. 13 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContactServiceImpl.java
  62. 653 61
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  63. 16 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerMessageServiceImpl.java
  64. 235 15
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/PartnerInfoServiceImpl.java
  65. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContactServiceImpl.java
  66. 63 36
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContractServiceImpl.java
  67. 246 14
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoServiceImpl.java
  68. 28 8
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoTemporaryServiceImpl.java
  69. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/utils/qcc/domain/Area.java
  70. 7 0
      ruoyi-modules/ruoyi-customer/src/main/resources/mapper/customer/TeamMemberMapper.xml
  71. 230 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/erp/ErpPullController.java
  72. 18 4
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyCommonController.java
  73. 76 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/tongji/TongJiPullController.java
  74. 30 22
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/tongji/TongJiPushController.java
  75. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java
  76. 3 5
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java
  77. 0 202
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/OrderCreateMessageHandler.java
  78. 8 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalItemServiceImpl.java
  79. 3 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalProductServiceImpl.java
  80. 32 3
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteTongJiPullServiceImpl.java
  81. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/MallMessageDispatcher.java
  82. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/MallMessageHandler.java
  83. 6 4
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java
  84. 65 31
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/TongjiPushStrategy.java
  85. 7 6
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/YangGuangPushStrategy.java
  86. 19 16
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ZhongChePushStrategy.java
  87. 7 7
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ZhongZhiPushStrategy.java
  88. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AccountActiveMessageHandler.java
  89. 15 3
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleApplyMessageHandler.java
  90. 9 3
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleCancelMessageHandler.java
  91. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleDeliverMessageHandler.java
  92. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleReceiveConfirmMessageHandler.java
  93. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleRefundNoticeMessageHandler.java
  94. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillAbnormalPassMessageHandler.java
  95. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillConfirmMessageHandler.java
  96. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillCreateMessageHandler.java
  97. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillFinishMessageHandler.java
  98. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillModifyMessageHandler.java
  99. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillRejctPassMessageHandler.java
  100. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillRuleCreateMessageHandler.java

+ 8 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerContactService.java

@@ -2,7 +2,15 @@ package org.dromara.customer.api;
 
 import org.dromara.customer.api.domain.vo.RemoteCustomerContactVo;
 
+import java.util.Map;
+import java.util.Set;
+
 public interface RemoteCustomerContactService {
 
     RemoteCustomerContactVo selectCustomerContactByCustomerIdAndUserId(Long customerId, Long userId);
+
+    /**
+     * 根据联系人ID批量查询联系人信息(含部门名称、联系人姓名)
+     */
+    Map<Long, RemoteCustomerContactVo> selectCustomerContactByIds(Set<Long> contactIds);
 }

+ 5 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java

@@ -43,4 +43,9 @@ public interface RemoteCustomerService {
 
     CustomerAddressDTO addReceiverAddress(String provinceId, String cityId, String countyId, String address, String mobile);
 
+    /**
+     * 是否需要确认订单
+     */
+    Boolean isNeedAffirmOrder(Long customerId);
+
 }

+ 13 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/dto/CustomerInfoDTO.java

@@ -36,7 +36,20 @@ public class CustomerInfoDTO implements Serializable {
      */
     private String status;
 
+    /**
+     * 省份编码
+     */
+    private String regProvincialNo;
 
+    /**
+     * 城市编码
+     */
+    private String regCityNo;
+
+    /**
+     * 区县编码
+     */
+    private String regCountyNo;
 
 
 }

+ 6 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/service/RemoteExternalItemService.java

@@ -2,6 +2,9 @@ package org.dromara.external.api.service;
 
 import org.dromara.external.api.domain.ExternalItemDto;
 
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author
  * @date 2026/3/27 上午12:30
@@ -11,4 +14,7 @@ public interface RemoteExternalItemService {
     * 获取项目信息
     * */
     ExternalItemDto getItemInfo(Long itemId);
+
+    /*批量根据项目key查询项目名称*/
+    Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys);
 }

+ 36 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyLogisticsCompanyDto.java

@@ -0,0 +1,36 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 物流公司响应数据
+ *
+ * @author
+ * @date 2026/6/9
+ */
+@Data
+public class ThirdpartyLogisticsCompanyDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /**
+     * 物流公司编号
+     */
+    private String logisticsNo;
+
+    /**
+     * 物流公司编码
+     */
+    private String logisticsCode;
+
+    /**
+     * 物流公司名称
+     */
+    private String logisticsName;
+}

+ 10 - 3
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/tongji/RemoteTongJiPullService.java

@@ -4,11 +4,12 @@ import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleConfirmBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleRefundBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleRejectBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleReturnReceivedBo;
+import org.dromara.common.core.domain.zhongche.vo.OrderDetailVo;
 import org.dromara.common.core.exception.api.ZhongcheException;
-import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
-import org.dromara.external.api.zhongche.domain.bo.OrderRejectBo;
-import org.dromara.external.api.zhongche.domain.bo.ZhongCheOrderDeliverBo;
+import org.dromara.external.api.zhongche.domain.bo.*;
+import org.dromara.external.api.zhongche.domain.vo.AreaVo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
+import org.dromara.external.api.zhongche.domain.vo.PendingOrderListVo;
 import org.dromara.external.api.zhongche.domain.vo.ZhongCheOrderDeliverVo;
 
 /**
@@ -16,6 +17,8 @@ import org.dromara.external.api.zhongche.domain.vo.ZhongCheOrderDeliverVo;
  * 时间:2026/2/25,17:49
  */
 public interface RemoteTongJiPullService {
+    //获取地区
+    AreaVo areaQuery(AreaQueryBo bo);
     //接单
     GoodsUpdateVo mallOrderConfirm(OrderConfirmBo bo) throws ZhongcheException;
     //拒单
@@ -30,4 +33,8 @@ public interface RemoteTongJiPullService {
     GoodsUpdateVo mallAftersaleRefund(AfterSaleRefundBo bo) throws ZhongcheException;
     //发货
     ZhongCheOrderDeliverVo mallOrderDeliverGoods(ZhongCheOrderDeliverBo bo) throws ZhongcheException;
+    //查询待处理的订单
+    PendingOrderListVo mallOrderPendingList(PendingOrderListBo bo);
+    //查询订单详情
+    OrderDetailVo mallOrderDetail(OrderDetailBo bo);
 }

+ 36 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/RemoteOrderInfoService.java

@@ -1,6 +1,12 @@
 package org.dromara.product.api;
 
+import org.dromara.product.api.domain.dto.HotProductRankingDto;
+import org.dromara.product.api.domain.dto.LatestOrderDto;
+import org.dromara.product.api.domain.dto.OrderAmountTrendDto;
 import org.dromara.product.api.domain.dto.OrderStatusCountDto;
+import org.dromara.product.api.domain.dto.PartnerOrderIndexDto;
+
+import java.util.List;
 
 /**
  * @author
@@ -12,4 +18,34 @@ public interface RemoteOrderInfoService {
      * @param itemKey 项目key
     * */
     OrderStatusCountDto getOrderStatusCount(String itemKey);
+
+    /**
+     * 获取最新订单列表
+     * @param itemKey 项目key
+     * @param limit 查询条数
+     * @return 最新订单列表
+     */
+    List<LatestOrderDto> getLatestOrders(String itemKey, int limit);
+
+    /**
+     * 获取本月订单金额趋势(按天汇总)
+     * @param itemKey 项目key
+     * @return 每日订单金额列表
+     */
+    List<OrderAmountTrendDto> getOrderAmountTrend(String itemKey);
+
+    /**
+     * 获取热销商品排行榜
+     * @param itemKey 项目key
+     * @param limit 排行数量
+     * @return 热销商品排行列表
+     */
+    List<HotProductRankingDto> getHotProductRankings(String itemKey, int limit);
+
+    /**
+     * 获取伙伴商协同平台首页订单统计数据
+     * @param partnerId 伙伴商ID
+     * @return 订单统计数据
+     */
+    PartnerOrderIndexDto getPartnerOrderIndex(Long partnerId);
 }

+ 26 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/HotProductRankingDto.java

@@ -0,0 +1,26 @@
+package org.dromara.product.api.domain.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 热销商品排行DTO
+ *
+ * @date 2026-06-01
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class HotProductRankingDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 商品名称 */
+    private String productName;
+
+    /** 销量 */
+    private Long salesCount;
+}

+ 39 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/LatestOrderDto.java

@@ -0,0 +1,39 @@
+package org.dromara.product.api.domain.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 最新订单DTO
+ *
+ * @date 2026-06-01
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class LatestOrderDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 订单编号 */
+    private String orderNo;
+
+    /** 客户名称 */
+    private String customerName;
+
+    /** 商品信息(第一个商品名称) */
+    private String productName;
+
+    /** 订单金额 */
+    private BigDecimal amount;
+
+    /** 订单状态 */
+    private String orderStatus;
+
+    /** 下单时间 */
+    private String orderTime;
+}

+ 27 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/OrderAmountTrendDto.java

@@ -0,0 +1,27 @@
+package org.dromara.product.api.domain.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 订单金额趋势DTO
+ *
+ * @date 2026-06-01
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderAmountTrendDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 日期 */
+    private String date;
+
+    /** 金额 */
+    private BigDecimal amount;
+}

+ 131 - 0
ruoyi-api/ruoyi-api-order/src/main/java/org/dromara/product/api/domain/dto/PartnerOrderIndexDto.java

@@ -0,0 +1,131 @@
+package org.dromara.product.api.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 伙伴商协同平台订单统计数据DTO
+ *
+ * @author LionLi
+ * @date 2026-06-01
+ */
+@Data
+public class PartnerOrderIndexDto implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 今日新增订单数
+     */
+    private Long todayOrders;
+
+    /**
+     * 本周销售总额
+     */
+    private BigDecimal weekRevenue;
+
+    /**
+     * 待发货数量
+     */
+    private Long pendingShipment;
+
+    /**
+     * 近7天发货量走势
+     */
+    private List<DayShipment> shipmentTrend;
+
+    /**
+     * 商品类型销售占比
+     */
+    private List<TypeSales> productTypeSales;
+
+    /**
+     * 最新发货动态
+     */
+    private List<ShipmentOrder> latestShipments;
+
+    /**
+     * 每日发货量
+     */
+    @Data
+    public static class DayShipment implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 日期,格式: "MM-dd"
+         */
+        private String date;
+
+        /**
+         * 发货量
+         */
+        private Long count;
+    }
+
+    /**
+     * 商品类型销售占比
+     */
+    @Data
+    public static class TypeSales implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 类型名称
+         */
+        private String name;
+
+        /**
+         * 销售数量/金额
+         */
+        private Long value;
+    }
+
+    /**
+     * 发货订单
+     */
+    @Data
+    public static class ShipmentOrder implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 订单编号
+         */
+        private String orderNo;
+
+        /**
+         * 商品名称
+         */
+        private String productName;
+
+        /**
+         * 订单金额
+         */
+        private BigDecimal amount;
+
+        /**
+         * 收货人
+         */
+        private String customer;
+
+        /**
+         * 发货状态
+         */
+        private String status;
+
+        /**
+         * 时间
+         */
+        private String date;
+    }
+}

+ 5 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductService.java

@@ -125,5 +125,10 @@ public interface RemoteProductService {
      */
     Long getProductIdProductNo(String productNo);
 
+    /**
+     * 获取商品总数
+     * @return 商品总数
+     */
+    Long getTotalProductCount();
 
 }

+ 5 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/CategoryDto.java

@@ -134,6 +134,11 @@ public class CategoryDto implements Serializable {
      */
     private Long reviewerId;
 
+    /**
+     * 客户id
+     * */
+    private Long customerId;
+
     /**
      * 子分类列表(用于树形结构)
      */

+ 11 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCurrencyService.java

@@ -3,7 +3,18 @@ package org.dromara.system.api;
 import org.dromara.system.api.domain.vo.RemoteComCompanyVo;
 import org.dromara.system.api.domain.vo.RemoteComCurrencyVo;
 
+import java.util.List;
+import java.util.Set;
+
 public interface RemoteComCurrencyService {
 
     RemoteComCurrencyVo selectByCurrencyName(String currencyName);
+
+    /**
+     * 根据ID集合批量查询交易币别
+     *
+     * @param ids 交易币别ID集合
+     * @return 交易币别VO列表
+     */
+    List<RemoteComCurrencyVo> selectCurrencyByIds(Set<Long> ids);
 }

+ 11 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComCustomerTypeService.java

@@ -3,6 +3,17 @@ package org.dromara.system.api;
 import org.dromara.system.api.domain.vo.RemoteComCustomerLevelVo;
 import org.dromara.system.api.domain.vo.RemoteComCustomerTypeVo;
 
+import java.util.List;
+import java.util.Set;
+
 public interface RemoteComCustomerTypeService {
     RemoteComCustomerTypeVo selectCustomerTypeByTypeName(String typeName);
+
+    /**
+     * 根据ID集合批量查询客户类型
+     *
+     * @param ids 客户类型ID集合
+     * @return 客户类型VO列表
+     */
+    List<RemoteComCustomerTypeVo> selectCustomerTypeByIds(Set<Long> ids);
 }

+ 2 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComLogisticsCompanyService.java

@@ -21,4 +21,6 @@ public interface RemoteComLogisticsCompanyService {
     * 通过名称获取id
     * */
     RemoteLogisticsCompanyVo selectLogisticsCompanyByName(String name);
+
+    List<RemoteLogisticsCompanyVo> selectLogisticsCompanyList();
 }

+ 2 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteComStaffService.java

@@ -22,6 +22,8 @@ public interface RemoteComStaffService {
 
     RemoteComStaffVo selectStaffByStaffName(String staffName);
 
+    RemoteComStaffVo selectStaffByStaffCode(String staffCode);
+
     RemoteComStaffVo selectStaffByUserId(Long userId);
 
 }

+ 2 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteErpStaffService.java

@@ -11,6 +11,8 @@ public interface RemoteErpStaffService {
 
     Map<Long, String> selectStaffNameByIds(Set<Long> ids);
 
+    RemoteErpStaffVo selectStaffByStaffNameOne(String staffName);
+
     RemoteErpStaffVo selectStaffByStaffName(String staffName);
 
 }

+ 11 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteProductTaxrateService.java

@@ -3,7 +3,18 @@ package org.dromara.system.api;
 
 import org.dromara.system.api.domain.vo.RemoteProductTaxrateVo;
 
+import java.util.List;
+import java.util.Set;
+
 public interface RemoteProductTaxrateService {
 
     RemoteProductTaxrateVo selectByTaxrateNo(String taxrateNo);
+
+    /**
+     * 根据ID集合批量查询产品税率
+     *
+     * @param ids 产品税率ID集合
+     * @return 产品税率VO列表
+     */
+    List<RemoteProductTaxrateVo> selectTaxrateByIds(Set<Long> ids);
 }

+ 8 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSupplierLevelService.java

@@ -5,4 +5,12 @@ import org.dromara.system.api.domain.vo.RemoteSupplierLevelVo;
 public interface RemoteSupplierLevelService {
 
     RemoteSupplierLevelVo selectByLevelName(String levelName);
+
+    /**
+     * 根据ID查询供应商等级
+     *
+     * @param id 等级ID
+     * @return 供应商等级信息
+     */
+    RemoteSupplierLevelVo selectByLevelId(Long id);
 }

+ 7 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteSupplierTypeService.java

@@ -14,4 +14,11 @@ public interface RemoteSupplierTypeService {
 
     RemoteSupplierTypeVo selectByTypeName(String typeName);
 
+    /**
+     * 根据ID查询供应商类型
+     *
+     * @param id 类型ID
+     * @return 供应商类型信息
+     */
+    RemoteSupplierTypeVo selectByTypeId(Long id);
 }

+ 27 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteTaxCodeService.java

@@ -0,0 +1,27 @@
+package org.dromara.system.api;
+
+import org.dromara.system.api.domain.vo.RemoteTaxCodeVo;
+
+import java.util.List;
+
+/**
+ * 税率编码
+ * @author
+ * @date 2026/6/5 下午3:03
+ */
+public interface RemoteTaxCodeService {
+    /**
+    * 通过税率编码编号获取税率编码对象
+    * */
+    RemoteTaxCodeVo selectByTaxCodeNo(String taxCodeNo);
+
+    /**
+    * 通过税率Id获取税率编码对象
+    * */
+    RemoteTaxCodeVo selectByTaxCodeId(Long taxCodeId);
+
+    /**
+    * 获取所有的税率编码对象
+    * */
+    List<RemoteTaxCodeVo> selectAll(RemoteTaxCodeVo remoteTaxCodeVo);
+}

+ 7 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteSupplierTypeVo.java

@@ -21,4 +21,11 @@ public class RemoteSupplierTypeVo implements Serializable {
 
     private String typeName;
 
+    private String supplierTypeNo;
+
+    /**
+     * 名称
+     */
+    private String supplierTypeName;
+
 }

+ 85 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/vo/RemoteTaxCodeVo.java

@@ -0,0 +1,85 @@
+package org.dromara.system.api.domain.vo;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author
+ * @date 2026/6/5 下午3:04
+ */
+@Data
+@NoArgsConstructor
+public class RemoteTaxCodeVo  implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    private Long id;
+
+    /**
+     * 父级id
+     */
+    private Long parentId;
+
+    /**
+     * 货物和劳务名称
+     */
+    private String name;
+
+    /**
+     * 商品和服务分类简称
+     */
+    private String abbreviation;
+
+    /**
+     * 税收编码
+     */
+    private String taxationNo;
+
+    /**
+     * 合并编码
+     */
+    private String mergeNo;
+
+    /**
+     * 上级编码
+     */
+    private String parentNo;
+
+    /**
+     * 祖级列表
+     */
+    private String ancestors;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 是否有下级 0不存在 1存在
+     * */
+    private String isBottom;
+
+    /**
+     * 税率
+     * */
+    private BigDecimal taxrate;
+    /**
+     * 说明
+     * */
+    private String explain;
+
+}

+ 7 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/model/LoginUser.java

@@ -157,6 +157,13 @@ public class LoginUser implements Serializable {
      */
     private String openid;
 
+    /**
+    * pc端显示情况 0默认首页,1企业首页,2大客户首页
+    * */
+    private String pcDisplay;
+
+
+
     /**
      * 获取登录id
      */

+ 1 - 1
ruoyi-auth/src/main/java/org/dromara/auth/controller/Auth2Controller.java

@@ -36,7 +36,7 @@ import java.util.Objects;
 @SaIgnore
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/auth2")
+@RequestMapping("/")
 public class Auth2Controller {
 
     private final ObjectMapper objectMapper;

+ 119 - 0
ruoyi-auth/src/main/java/org/dromara/auth/service/impl/SerialNumberStrategy.java

@@ -0,0 +1,119 @@
+package org.dromara.auth.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.dev33.satoken.stp.parameter.SaLoginParameter;
+import cn.hutool.core.collection.CollUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.model.AuthResponse;
+import me.zhyd.oauth.model.AuthUser;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.auth.domain.vo.LoginVo;
+import org.dromara.auth.form.SocialLoginBody;
+import org.dromara.auth.service.IAuthStrategy;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.ValidatorUtils;
+import org.dromara.common.json.utils.JsonUtils;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.social.config.properties.SocialProperties;
+import org.dromara.common.social.utils.SocialUtils;
+import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.system.api.RemoteSocialService;
+import org.dromara.system.api.RemoteUserService;
+import org.dromara.system.api.domain.vo.RemoteClientVo;
+import org.dromara.system.api.domain.vo.RemoteSocialVo;
+import org.dromara.system.api.model.LoginUser;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 第三方授权策略
+ *
+ * @author thiszhc is 三三
+ */
+@Slf4j
+@Service("serialNumber" + IAuthStrategy.BASE_NAME)
+@RequiredArgsConstructor
+public class SerialNumberStrategy implements IAuthStrategy {
+
+    private final SocialProperties socialProperties;
+
+    @DubboReference
+    private RemoteSocialService remoteSocialService;
+    @DubboReference
+    private RemoteUserService remoteUserService;
+
+    /**
+     * 登录-第三方授权登录
+     *
+     * @param body     登录信息
+     * @param client   客户端信息
+     */
+    @Override
+    public LoginVo login(String body, RemoteClientVo client) {
+        SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class);
+        ValidatorUtils.validate(loginBody);
+        AuthResponse<AuthUser> response = SocialUtils.loginAuth(
+            loginBody.getSource(), loginBody.getSocialCode(),
+            loginBody.getSocialState(), socialProperties);
+        if (!response.ok()) {
+            throw new ServiceException(response.getMsg());
+        }
+        AuthUser authUserData = response.getData();
+
+        List<RemoteSocialVo> list = remoteSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
+        if (CollUtil.isEmpty(list)) {
+            throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
+        }
+        RemoteSocialVo socialVo;
+        if (TenantHelper.isEnable()) {
+            Optional<RemoteSocialVo> opt = StreamUtils.findAny(list, x -> x.getTenantId().equals(loginBody.getTenantId()));
+            if (opt.isEmpty()) {
+                throw new ServiceException("对不起,你没有权限登录当前租户!");
+            }
+            socialVo = opt.get();
+        } else {
+            socialVo = list.get(0);
+        }
+
+        LoginUser loginUser = remoteUserService.getUserInfo(socialVo.getUserId(), socialVo.getTenantId());
+        loginUser.setClientKey(client.getClientKey());
+        loginUser.setDeviceType(client.getDeviceType());
+        SaLoginParameter model = new SaLoginParameter();
+        model.setDeviceType(client.getDeviceType());
+        // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
+        // 例如: 后台用户30分钟过期 app用户1天过期
+        model.setTimeout(client.getTimeout());
+        model.setActiveTimeout(client.getActiveTimeout());
+        model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
+        // 生成token
+        LoginHelper.login(loginUser, model);
+
+        LoginVo loginVo = new LoginVo();
+        loginVo.setAccessToken(StpUtil.getTokenValue());
+        loginVo.setExpireIn(StpUtil.getTokenTimeout());
+        loginVo.setClientId(client.getClientId());
+        return loginVo;
+    }
+
+    /**
+     * 客户登录
+     *
+     * @param body   登录对象
+     * @param client 授权管理视图对象
+     * @return 登录验证信息
+     */
+    @Override
+    public LoginVo clientLogin(String body, RemoteClientVo client) {
+        return null;
+    }
+
+    @Override
+    public LoginVo getToken(String username, String password) {
+        return null;
+    }
+
+}

+ 5 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java

@@ -126,7 +126,10 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "mini_page_set",
         "maintain_info",
         "maintenance_server_item",
-        "ep_"
+        "contract_supply",
+        "team_member",
+        "ep_",
+        "dkh_"
         // 注意:前缀匹配需特殊处理(如 qrtz_),见 isIgnoreTable 方法
     ));
 
@@ -250,6 +253,7 @@ public class PlatformDataScopeInterceptor implements Interceptor {
             || tableName.startsWith("protocol_")
             || tableName.startsWith("ns_diy_")
             || tableName.startsWith("ep_")
+            || tableName.startsWith("dkh_")
             ;
     }
 

+ 1 - 1
ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java

@@ -51,7 +51,7 @@ public class GlobalExceptionHandler {
 
     @ExceptionHandler(ZhongcheException.class)
     public R<Void> handleZhongcheException(ZhongcheException e) {
-        log.error("中车系统异常 : {}", e.getMessage());
+        log.error("系统异常 : {}", e.getMessage());
         return R.fail(e.getMessage());
     }
 

+ 1 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/controller/pc/PcStatementProductController.java

@@ -1,5 +1,6 @@
 package org.dromara.bill.controller.pc;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;

+ 4 - 0
ruoyi-modules/ruoyi-customer/pom.xml

@@ -123,6 +123,10 @@
             <groupId>org.dromara</groupId>
             <artifactId>ruoyi-api-product</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-api-order</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 6 - 6
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/ContractSupplyController.java

@@ -41,7 +41,7 @@ public class ContractSupplyController extends BaseController {
     /**
      * 查询协议供货列表
      */
-    @SaCheckPermission("supplier:contractsupply:list")
+    //@SaCheckPermission("supplier:contractsupply:list")
     @GetMapping("/list")
     public TableDataInfo<ContractSupplyVo> list(ContractSupplyBo bo, PageQuery pageQuery) {
         return contractSupplyService.queryPageList(bo, pageQuery);
@@ -50,7 +50,7 @@ public class ContractSupplyController extends BaseController {
     /**
      * 导出协议供货列表
      */
-    @SaCheckPermission("supplier:contractsupply:export")
+    //@SaCheckPermission("supplier:contractsupply:export")
     @Log(title = "协议供货", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(ContractSupplyBo bo, HttpServletResponse response) {
@@ -63,7 +63,7 @@ public class ContractSupplyController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("supplier:contractsupply:query")
+    //@SaCheckPermission("supplier:contractsupply:query")
     @GetMapping("/{id}")
     public R<ContractSupplyVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {
@@ -74,7 +74,7 @@ public class ContractSupplyController extends BaseController {
     /**
      * 新增协议供货
      */
-    @SaCheckPermission("supplier:contractsupply:add")
+    //@SaCheckPermission("supplier:contractsupply:add")
     @Log(title = "协议供货", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
@@ -86,7 +86,7 @@ public class ContractSupplyController extends BaseController {
     /**
      * 修改协议供货
      */
-    @SaCheckPermission("supplier:contractsupply:edit")
+    //@SaCheckPermission("supplier:contractsupply:edit")
     @Log(title = "协议供货", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()
@@ -112,7 +112,7 @@ public class ContractSupplyController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("supplier:contractsupply:remove")
+    //@SaCheckPermission("supplier:contractsupply:remove")
     @Log(title = "协议供货", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空")

+ 28 - 8
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java

@@ -17,17 +17,12 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.web.core.BaseController;
-import org.dromara.customer.domain.bo.CustomerClaimBo;
-import org.dromara.customer.domain.bo.CustomerInfoBo;
-import org.dromara.customer.domain.bo.CustomerListBo;
-import org.dromara.customer.domain.bo.CustomerSalesInfoBo;
-import org.dromara.customer.domain.bo.MessagePublishCustomerBo;
-import org.dromara.customer.domain.dto.SetCustomerInfoTagDto;
+import org.dromara.customer.domain.bo.*;
 import org.dromara.customer.domain.dto.ReleaseToPoolDto;
+import org.dromara.customer.domain.dto.SetCustomerInfoTagDto;
 import org.dromara.customer.domain.vo.*;
 import org.dromara.customer.listener.CustomerImportListener;
 import org.dromara.customer.service.ICustomerInfoService;
-import org.dromara.system.api.RemoteProductTaxrateService;
 import org.dromara.system.api.*;
 import org.dromara.system.api.domain.vo.RemoteComCompanyVo;
 import org.dromara.system.api.domain.vo.RemoteComCustomerLevelVo;
@@ -74,9 +69,25 @@ public class CustomerInfoController extends BaseController {
 
     private final ICustomerInfoService customerInfoService;
 
+    /**
+     * 客户首页数据
+     */
+    @GetMapping("/customerIndexData")
+    public R<CustomerIndexDataVo> customerIndexData() {
+        return customerInfoService.customerIndexData();
+    }
+
     /**
      * 查询客户信息列表
+     * <p>数据权限通过框架 @DataPermission 注解自动处理,
+     * 根据角色数据范围(全部/本部门/本部门及以下/仅本人)自动过滤</p>
      */
+//    @DataPermission({
+//        @DataColumn(key = "deptName", value = "create_dept"),
+//        @DataColumn(key = "userName", value = "create_by"),
+//        @DataColumn(key = "salesPersonName", value = "sales_person_id"),
+//        @DataColumn(key = "serviceStaffName", value = "service_staff_id")
+//    })
     @GetMapping("/list")
     public TableDataInfo<CustomerInfoVo> list(CustomerInfoBo bo, PageQuery pageQuery) {
         Long userId = LoginHelper.getLoginUser().getUserId();
@@ -90,7 +101,6 @@ public class CustomerInfoController extends BaseController {
             bo.setSalesPersonId(staffId);
             bo.setServiceStaffId(staffId);
         }
-
         return customerInfoService.queryPageList(bo, pageQuery);
     }
 
@@ -281,6 +291,16 @@ public class CustomerInfoController extends BaseController {
         ExcelUtil.exportExcel(new ArrayList<>(), "客户数据", CustomerInfoImportVo.class, response);
     }
 
+    /**
+     * 导出模板数据(带30条真实客户数据)
+     */
+    @Log(title = "客户信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/exportTemplateData")
+    public void exportTemplateData(HttpServletResponse response) {
+        List<CustomerInfoImportVo> list = customerInfoService.queryImportTemplateList(9999);
+        ExcelUtil.exportExcel(list, "客户数据", CustomerInfoImportVo.class, response);
+    }
+
     /**
      * 获取公司下拉列表
      */

+ 41 - 17
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/PartnerInfoController.java

@@ -1,28 +1,32 @@
 package org.dromara.customer.controller;
 
-import java.util.List;
-
-import lombok.RequiredArgsConstructor;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
-import org.dromara.common.core.utils.StringUtils;
-import org.dromara.customer.domain.vo.CustomerInfoVo;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.validation.annotation.Validated;
-import org.dromara.common.idempotent.annotation.RepeatSubmit;
-import org.dromara.common.log.annotation.Log;
-import org.dromara.common.web.core.BaseController;
-import org.dromara.common.mybatis.core.page.PageQuery;
+import cn.hutool.core.util.ObjectUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.core.validate.AddGroup;
 import org.dromara.common.core.validate.EditGroup;
-import org.dromara.common.log.enums.BusinessType;
 import org.dromara.common.excel.utils.ExcelUtil;
-import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
 import org.dromara.customer.domain.bo.PartnerInfoBo;
+import org.dromara.customer.domain.vo.PartnerInfoIndexDataVo;
+import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.dromara.customer.domain.vo.PartnerManageIndexDataVo;
 import org.dromara.customer.service.IPartnerInfoService;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
 
 /**
  * 伙伴商基本信息
@@ -39,6 +43,26 @@ public class PartnerInfoController extends BaseController {
 
     private final IPartnerInfoService partnerInfoService;
 
+    /**
+     * 伙伴商管理平台首页数据
+     */
+    @GetMapping("/partnerManageIndexData")
+    public R<PartnerManageIndexDataVo> partnerManageIndexData() {
+        return partnerInfoService.partnerManageIndexData();
+    }
+
+    /**
+     * 伙伴商协同平台首页数据
+     */
+    @GetMapping("/partnerInfoIndexData")
+    public R<PartnerInfoIndexDataVo> partnerInfoIndexData() {
+        Long partnerId = LoginHelper.getLoginUser().getPartnerId();
+        if (ObjectUtil.isEmpty(partnerId)) {
+            return R.fail("未获取到当前伙伴商信息");
+        }
+        return partnerInfoService.partnerInfoIndexData(partnerId);
+    }
+
     /**
      * 查询伙伴商基本信息列表
      */
@@ -67,7 +91,7 @@ public class PartnerInfoController extends BaseController {
     @SaCheckPermission("customer:partnerInfo:query")
     @GetMapping("/{id}")
     public R<PartnerInfoVo> getInfo(@NotNull(message = "主键不能为空")
-                                     @PathVariable("id") Long id) {
+                                    @PathVariable("id") Long id) {
         return R.ok(partnerInfoService.queryById(id));
     }
 

+ 10 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierInfoController.java

@@ -256,6 +256,16 @@ public class SupplierInfoController extends BaseController {
         ExcelUtil.exportExcel(new ArrayList<>(), "供应商数据", SupplierInfoImportVo.class, response);
     }
 
+    /**
+     * 导出模板数据(带30条真实供应商数据)
+     */
+    @Log(title = "供应商信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/exportTemplateData")
+    public void exportTemplateData(HttpServletResponse response) {
+        List<SupplierInfoImportVo> list = supplierInfoService.queryImportTemplateList(0);
+        ExcelUtil.exportExcel(list, "供应商数据", SupplierInfoImportVo.class, response);
+    }
+
     /**
      * 获取供应商名称模糊查询供应商列表信息
      *

+ 12 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcCustomerMessageController.java

@@ -40,6 +40,18 @@ public class PcCustomerMessageController extends BaseController {
         return customerMessageService.queryPageList(bo, pageQuery);
     }
 
+    /**
+     * 查询客户最新公告
+     */
+    @GetMapping("/getNewNotice")
+    public R<CustomerMessageVo> getNewNotice() {
+        // 获取当前登录用户的企业ID
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
+        CustomerMessageBo bo = new CustomerMessageBo();
+        bo.setCustomerId(customerId);
+        return R.ok(customerMessageService.getNewNotice(bo));
+    }
+
     /**
      * 获取客户消息详细信息
      *

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerMessage.java

@@ -73,5 +73,10 @@ public class CustomerMessage extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 封面图片
+     */
+    private String coverUrl;
+
 
 }

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierQualification.java

@@ -97,5 +97,10 @@ public class SupplierQualification extends TenantEntity {
      */
     private String remark;
 
+    /**
+     * 0=待提交,1=生效,2=禁用
+     * */
+    private String qualificationStatus;
+
 
 }

+ 1 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerInfoBo.java

@@ -175,7 +175,7 @@ public class CustomerInfoBo extends BaseEntity {
     private String provincialCityCounty;
 
     /**
-     * 状态(0正常 1停用)
+     * 状态(1正常 0停用)
      */
     private String status;
 

+ 4 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerMessageBo.java

@@ -65,5 +65,8 @@ public class CustomerMessageBo extends BaseEntity {
      */
     private String remark;
 
-
+    /**
+     * 封面图片
+     */
+    private String coverUrl;
 }

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierQualificationBo.java

@@ -81,5 +81,10 @@ public class SupplierQualificationBo extends BaseEntity {
 
     private String remark;
 
+    /**
+     * 0=待提交,1=生效,2=禁用
+     * */
+    private String qualificationStatus;
+
 
 }

+ 103 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerIndexDataVo.java

@@ -0,0 +1,103 @@
+package org.dromara.customer.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 客户首页数据看板VO
+ *
+ * @date 2026-06-01
+ */
+@Data
+public class CustomerIndexDataVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 总客户数 */
+    private Long totalCustomers;
+
+    /** 总订单数 */
+    private Long totalOrders;
+
+    /** 商品总量 */
+    private Long totalProducts;
+
+    /** 本月营收 */
+    private BigDecimal monthlyRevenue;
+
+    /** 最近七天客户趋势 */
+    private List<TrendItem> customerTrend;
+
+    /** 本月订单金额趋势 */
+    private List<TrendItem> orderAmountTrend;
+
+    /** 客户类型分布 */
+    private List<TypeDistribution> customerTypeDistribution;
+
+    /** 最新订单明细 */
+    private List<LatestOrder> latestOrders;
+
+    /** 热销商品排行榜 */
+    private List<HotProduct> hotProductRankings;
+
+    /**
+     * 趋势数据项
+     */
+    @Data
+    public static class TrendItem implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 日期 */
+        private String date;
+        /** 数量/金额 */
+        private BigDecimal value;
+    }
+
+    /**
+     * 类型分布
+     */
+    @Data
+    public static class TypeDistribution implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 类型名称 */
+        private String name;
+        /** 数量 */
+        private Long value;
+    }
+
+    /**
+     * 最新订单
+     */
+    @Data
+    public static class LatestOrder implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 订单编号 */
+        private String orderNo;
+        /** 客户名称 */
+        private String customer;
+        /** 商品信息 */
+        private String product;
+        /** 金额 */
+        private BigDecimal amount;
+        /** 状态 */
+        private String status;
+        /** 下单时间 */
+        private String date;
+    }
+
+    /**
+     * 热销商品
+     */
+    @Data
+    public static class HotProduct implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 商品名称 */
+        private String name;
+        /** 销量 */
+        private Long sales;
+        /** 百分比 */
+        private Integer percentage;
+    }
+}

+ 45 - 3
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerInfoImportVo.java

@@ -106,6 +106,24 @@ public class CustomerInfoImportVo implements Serializable {
     @ExcelProperty(value = "企业规模名称")
     private String enterpriseScale;
 
+    /**
+     * 省
+     */
+    @ExcelProperty(value = "省")
+    private String provinceNo;
+
+    /**
+     * 市
+     */
+    @ExcelProperty(value = "市")
+    private String cityNo;
+
+    /**
+     * 区
+     */
+    @ExcelProperty(value = "区")
+    private String areaNo;
+
     /**
      * 详细地址
      */
@@ -113,10 +131,34 @@ public class CustomerInfoImportVo implements Serializable {
     private String address;
 
     /**
-     * 发票地址
+     * 系统人员--业务负责人
      */
-    @ExcelProperty(value = "发票地址")
-    private String invoiceAddress;
+    @ExcelProperty(value = "项目负责人编号")
+    private String xtSalesPersonNo;
+
+    /**
+     * 系统人员--业务负责人
+     */
+    @ExcelProperty(value = "项目负责人名称")
+    private String xtSalesPersonName;
+
+    /**
+     * 系统人员--客服支持
+     */
+    @ExcelProperty(value = "客服支持编号")
+    private String xtServiceStaffNo;
+
+    /**
+     * 系统人员--客服支持
+     */
+    @ExcelProperty(value = "客服支持名称")
+    private String xtServiceStaffName;
+
+//    /**
+//     * 发票地址
+//     */
+//    @ExcelProperty(value = "发票地址")
+//    private String invoiceAddress;
 
     /**
      * 销售人员--业务人员

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerMessageVo.java

@@ -66,4 +66,9 @@ public class CustomerMessageVo implements Serializable {
     private Date createTime;
 
     private String status;
+
+    /**
+     * 封面图片
+     */
+    private String coverUrl;
 }

+ 136 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/PartnerInfoIndexDataVo.java

@@ -0,0 +1,136 @@
+package org.dromara.customer.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 伙伴商协同平台首页数据视图对象
+ *
+ * @author LionLi
+ * @date 2026-06-01
+ */
+@Data
+public class PartnerInfoIndexDataVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 今日新增订单
+     */
+    private Long todayOrders;
+
+    /**
+     * 本周销售总额
+     */
+    private BigDecimal weekRevenue;
+
+    /**
+     * 待发货数量
+     */
+    private Long pendingShipment;
+
+    /**
+     * 在售商品数
+     */
+    private Long onSaleProducts;
+
+    /**
+     * 近期订单发货量走势
+     */
+    private List<ShipmentTrend> shipmentTrend;
+
+    /**
+     * 商品类型销售占比
+     */
+    private List<ProductTypeSales> productTypeSales;
+
+    /**
+     * 最新发货动态
+     */
+    private List<LatestShipment> latestShipments;
+
+    /**
+     * 发货量走势
+     */
+    @Data
+    public static class ShipmentTrend implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 日期,格式: "MM-dd"
+         */
+        private String date;
+
+        /**
+         * 发货量
+         */
+        private Long count;
+    }
+
+    /**
+     * 商品类型销售占比
+     */
+    @Data
+    public static class ProductTypeSales implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 类型名称
+         */
+        private String name;
+
+        /**
+         * 销售数量/金额
+         */
+        private Long value;
+    }
+
+    /**
+     * 最新发货订单
+     */
+    @Data
+    public static class LatestShipment implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 订单编号
+         */
+        private String orderNo;
+
+        /**
+         * 商品名称
+         */
+        private String productName;
+
+        /**
+         * 订单金额
+         */
+        private BigDecimal amount;
+
+        /**
+         * 收货人
+         */
+        private String customer;
+
+        /**
+         * 发货状态
+         */
+        private String status;
+
+        /**
+         * 时间
+         */
+        private String date;
+    }
+}

+ 82 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/PartnerManageIndexDataVo.java

@@ -0,0 +1,82 @@
+package org.dromara.customer.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 伙伴商管理平台首页数据
+ *
+ * @author LionLi
+ * @date 2026-06-01
+ */
+@Data
+public class PartnerManageIndexDataVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 伙伴商总数 */
+    private Long partnerTotal;
+
+    /** 本月新增入驻 */
+    private Long monthlyNew;
+
+    /** 季度新增入驻 */
+    private Long quarterlyNew;
+
+    /** 合作中项目数(PartnerContract中cooperationId去重) */
+    private Long cooperationProjectCount;
+
+    /** 近半年新增伙伴商趋势 */
+    private List<MonthTrend> monthlyTrend;
+
+    /** 伙伴合作型态分布 */
+    private List<TypeDistribution> typeDistribution;
+
+    /** 最新入驻伙伴商列表(最新8条) */
+    private List<LatestPartner> latestPartners;
+
+    /**
+     * 月度趋势
+     */
+    @Data
+    public static class MonthTrend implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 月份标签,如"5月" */
+        private String month;
+        /** 新增数量 */
+        private Long count;
+    }
+
+    /**
+     * 合作型态分布
+     */
+    @Data
+    public static class TypeDistribution implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 类型名称 */
+        private String name;
+        /** 数量 */
+        private Long value;
+    }
+
+    /**
+     * 最新入驻伙伴商
+     */
+    @Data
+    public static class LatestPartner implements Serializable {
+        private static final long serialVersionUID = 1L;
+        /** 伙伴商名称 */
+        private String companyName;
+        /** 联系人 */
+        private String contact;
+        /** 联系电话 */
+        private String phone;
+        /** 合作型态 */
+        private Long partnerCooperateType;
+        /** 申请时间 */
+        private String joinTime;
+    }
+}

+ 25 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoImportVo.java

@@ -69,6 +69,12 @@ public class SupplierInfoImportVo implements Serializable {
     @ExcelProperty(value = "姓名")
     private String buyerName;
 
+    /**
+     * 采购员
+     */
+    @ExcelProperty(value = "采购员")
+    private String buyerOne;
+
     /**
      * 付款类型
      */
@@ -105,6 +111,25 @@ public class SupplierInfoImportVo implements Serializable {
     @ExcelProperty(value = "办公电话")
     private String fixedPhone;
 
+    /**
+     * 省
+     */
+    @ExcelProperty(value = "省")
+    private String officeProvince;
+
+    /**
+     * 市
+     */
+    @ExcelProperty(value = "市")
+    private String officeCity;
+
+    /**
+     * 区
+     */
+    @ExcelProperty(value = "区")
+    private String officeCounty;
+
+
     /**
      * 联系地址
      */

+ 6 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoVo.java

@@ -41,6 +41,12 @@ public class SupplierInfoVo implements Serializable {
     @ExcelProperty(value = "主键ID")
     private Long id;
 
+    /**
+    * supplier_id
+    * */
+    @ExcelProperty(value = "supplier_id")
+    private Long supplierId;
+
     /**
      * 供应商编号
      */

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierQualificationVo.java

@@ -107,5 +107,10 @@ public class SupplierQualificationVo implements Serializable {
 
     private String remark;
 
+    /**
+     * 0=待提交,1=生效,2=禁用
+     * */
+    private String qualificationStatus;
+
 
 }

+ 18 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerContactServiceImpl.java

@@ -10,6 +10,11 @@ import org.dromara.customer.domain.vo.CustomerContactVo;
 import org.dromara.customer.service.ICustomerContactService;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 @Slf4j
 @Service
 @RequiredArgsConstructor
@@ -23,4 +28,17 @@ public class RemoteCustomerContactServiceImpl implements RemoteCustomerContactSe
         CustomerContactVo customerContactVo = customerContactService.selectCustomerContactByCustomerIdAndUserId(customerId, userId);
         return BeanUtil.toBean(customerContactVo, RemoteCustomerContactVo.class);
     }
+
+    @Override
+    public Map<Long, RemoteCustomerContactVo> selectCustomerContactByIds(Set<Long> contactIds) {
+        if (contactIds == null || contactIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        return customerContactService.selectContactByIds(contactIds)
+            .entrySet().stream()
+            .collect(Collectors.toMap(
+                Map.Entry::getKey,
+                e -> BeanUtil.toBean(e.getValue(), RemoteCustomerContactVo.class)
+            ));
+    }
 }

+ 4 - 2
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java

@@ -2,7 +2,6 @@ package org.dromara.customer.dubbo;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import com.baomidou.mybatisplus.core.toolkit.BeanUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -146,5 +145,8 @@ public class RemoteCustomerServiceImpl implements RemoteCustomerService {
         return customerAddressDTO;
     }
 
-
+    @Override
+    public Boolean isNeedAffirmOrder(Long customerId) {
+        return customerInfoService.isNeedAffirmOrder(customerId);
+    }
 }

+ 14 - 4
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteSupplierInfoServiceImpl.java

@@ -11,9 +11,7 @@ import org.dromara.customer.api.domain.dto.SupplierAreaDTO;
 import org.dromara.customer.api.domain.dto.SupplierAuthorizeDTO;
 import org.dromara.customer.domain.ContractSupply;
 import org.dromara.customer.domain.SupplierContact;
-import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.SupplyArea;
-import org.dromara.customer.domain.vo.SupplyAreaVo;
 import org.dromara.customer.service.*;
 import org.springframework.stereotype.Service;
 
@@ -61,12 +59,15 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
     }
 
     @Override
-    public List<Long> getSupplierIdsBySupplyArea(String areaname,String level) {
-        return supplyAreaService.getSupplierIdsBySupplyArea(areaname,level);
+    public List<Long> getSupplierIdsBySupplyArea(String areaname, String level) {
+        return supplyAreaService.getSupplierIdsBySupplyArea(areaname, level);
     }
 
     @Override
     public List<Long> getContractIdBySupplySupplierID(Set<Long> SupplierID) {
+        if (CollUtil.isEmpty(SupplierID)) {
+            return Collections.emptyList();
+        }
         return contractSupplyService.list(
             Wrappers.lambdaQuery(ContractSupply.class)
                 .in(ContractSupply::getSupplierId, SupplierID)
@@ -76,6 +77,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, Long> contractToSupplierMap(List<Long> contractSupplyIds) {
+        if (CollUtil.isEmpty(contractSupplyIds)) {
+            return Collections.emptyMap();
+        }
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>().in(ContractSupply::getId, contractSupplyIds)
         );
@@ -86,6 +90,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, String> selectEnterpriseNameByIds(List<Long> ids) {
+        if (CollUtil.isEmpty(ids)) {
+            return Collections.emptyMap();
+        }
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>().in(ContractSupply::getId, ids)
         );
@@ -115,6 +122,9 @@ public class RemoteSupplierInfoServiceImpl implements RemoteSupplierInfoService
 
     @Override
     public Map<Long, SupplierAreaDTO> selectSupplierInfoByContractIds(List<Long> contractSupplyIds) {
+        if (CollUtil.isEmpty(contractSupplyIds)) {
+            return Collections.emptyMap();
+        }
         // 1 查询合同供货
         List<ContractSupply> list = contractSupplyService.list(
             new LambdaQueryWrapper<ContractSupply>()

+ 19 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/listener/CustomerImportListener.java

@@ -72,7 +72,8 @@ public class CustomerImportListener extends AnalysisEventListener<CustomerInfoIm
                                   RemoteComCustomerTypeService remoteComCustomerTypeService,
                                   RemoteProductTaxrateService remoteProductTaxrateService,
                                   RemoteComStaffService remoteComStaffService,
-                                  RemoteErpStaffService remoteErpStaffService) {
+                                  RemoteErpStaffService remoteErpStaffService
+                                  ) {
         this.customerInfoService = SpringUtils.getBean(ICustomerInfoService.class);
         this.remoteComCompanyService = remoteComCompanyService;
         this.remoteComCustomerLevelService = remoteComCustomerLevelService;
@@ -114,6 +115,8 @@ public class CustomerImportListener extends AnalysisEventListener<CustomerInfoIm
                 : customerInfoImportVo.getCreditLevel().equals("1") ? "B" : customerInfoImportVo.getCreditLevel().equals("2") ? "C"
                 : customerInfoImportVo.getCreditLevel().equals("3") ? "D" : customerInfoImportVo.getCreditLevel().equals("4") ? "E"
                 : customerInfoImportVo.getCreditLevel().equals("5") ? "F" : "G");
+            RemoteComStaffVo xtSalesPerson = remoteComStaffService.selectStaffByStaffCode(customerInfoImportVo.getXtSalesPersonNo());
+            RemoteComStaffVo xtServiceStaff = remoteComStaffService.selectStaffByStaffCode(customerInfoImportVo.getXtServiceStaffNo());
             RemoteErpStaffVo SalesPerson = remoteErpStaffService.selectStaffByStaffName(customerInfoImportVo.getSalesPersonNo());
             RemoteErpStaffVo ServiceStaff = remoteErpStaffService.selectStaffByStaffName(customerInfoImportVo.getServiceStaffNo());
             CustomerSalesInfoBo customerSalesInfo = new CustomerSalesInfoBo();
@@ -155,6 +158,14 @@ public class CustomerImportListener extends AnalysisEventListener<CustomerInfoIm
             // 验证是否存在这个客户
             if (ObjectUtil.isNull(customerInfo)) {
                 CustomerInfoBo customerInfoBo = BeanUtil.toBean(customerInfoImportVo, CustomerInfoBo.class);
+                customerInfoBo.setStatus("1");
+                if (ObjectUtil.isNotEmpty(xtSalesPerson)) {
+                    customerInfoBo.setSalesPersonId(xtSalesPerson.getStaffId());
+                    customerInfoBo.setBelongingDepartmentId(xtSalesPerson.getDeptId());
+                }
+                if (ObjectUtil.isNotEmpty(xtServiceStaff)) {
+                    customerInfoBo.setServiceStaffId(xtServiceStaff.getStaffId());
+                }
                 if (ObjectUtil.isNotEmpty(remoteComCompanyVo)) {
                     customerInfoBo.setBelongCompanyId(remoteComCompanyVo.getId());
                 }
@@ -183,6 +194,13 @@ public class CustomerImportListener extends AnalysisEventListener<CustomerInfoIm
                 Long customerId = customerInfo.getId();
                 CustomerInfoBo customerInfoBo = BeanUtil.toBean(customerInfoImportVo, CustomerInfoBo.class);
                 customerInfoBo.setId(customerId);
+                if (ObjectUtil.isNotEmpty(xtSalesPerson)) {
+                    customerInfoBo.setSalesPersonId(xtSalesPerson.getStaffId());
+                    customerInfoBo.setBelongingDepartmentId(xtSalesPerson.getDeptId());
+                }
+                if (ObjectUtil.isNotEmpty(xtServiceStaff)) {
+                    customerInfoBo.setServiceStaffId(xtServiceStaff.getStaffId());
+                }
                 if (ObjectUtil.isNotEmpty(remoteComCompanyVo)) {
                     customerInfoBo.setBelongCompanyId(remoteComCompanyVo.getId());
                 }

+ 12 - 4
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/CustomerInfoMapper.java

@@ -2,12 +2,14 @@ package org.dromara.customer.mapper;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
+import org.dromara.common.mybatis.annotation.DataColumn;
+import org.dromara.common.mybatis.annotation.DataPermission;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.customer.domain.CustomerInfo;
 import org.dromara.customer.domain.bo.CustomerInfoBo;
 import org.dromara.customer.domain.bo.CustomerListBo;
 import org.dromara.customer.domain.bo.MessagePublishCustomerBo;
 import org.dromara.customer.domain.vo.CustomerInfoVo;
-import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.customer.domain.vo.CustomerListVo;
 import org.dromara.customer.domain.vo.MessagePublishCustomerVo;
 
@@ -17,23 +19,29 @@ import org.dromara.customer.domain.vo.MessagePublishCustomerVo;
  * @author LionLi
  * @date 2025-12-11
  */
+//@DataPermission({
+//    @DataColumn(key = "deptName", value = "belonging_department_id"),
+//    @DataColumn(key = "userName", value = "create_by"),
+//    @DataColumn(key = "salesPersonName", value = "sales_person_id"),
+//    @DataColumn(key = "serviceStaffName", value = "service_staff_id")
+//})
 public interface CustomerInfoMapper extends BaseMapperPlus<CustomerInfo, CustomerInfoVo> {
 
     /**
      * 消息发布-分页查询客户列表
      */
     Page<MessagePublishCustomerVo> selectMessagePublishCustomerPage(@Param("page") Page<MessagePublishCustomerVo> page,
-                                                                     @Param("bo") MessagePublishCustomerBo bo);
+                                                                    @Param("bo") MessagePublishCustomerBo bo);
 
     /**
      * 客户列表-分页查询
      */
     Page<CustomerListVo> selectCustomerListPage(@Param("page") Page<CustomerListVo> page,
-                                                 @Param("bo") CustomerListBo bo);
+                                                @Param("bo") CustomerListBo bo);
 
     /**
      * 公海客户列表-分页查询(基于 customer_info 表,筛选无业务负责人的客户)
      */
     Page<CustomerInfoVo> selectHighSeasVoPage(@Param("page") Page<CustomerInfoVo> page,
-                                                @Param("bo") CustomerInfoBo bo);
+                                              @Param("bo") CustomerInfoBo bo);
 }

+ 9 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/TeamMemberMapper.java

@@ -37,6 +37,15 @@ public interface TeamMemberMapper extends BaseMapperPlus<TeamMember, TeamMemberV
      */
     TeamMemberVo selectByObjectNoAndUserNoWithDeleted(@Param("objectNo") String objectNo, @Param("userNo") Long userNo);
 
+    /**
+     * 根据对象编号和角色编码查询团队成员(包括已删除的)
+     *
+     * @param objectNo 对象编号(如客户编号)
+     * @param roleCode 角色编码
+     * @return 团队成员信息
+     */
+    TeamMemberVo selectByObjectNoAndRoleCodeWithDeleted(@Param("objectNo") String objectNo, @Param("roleCode") String roleCode);
+
     /**
      * 恢复已删除的团队成员记录
      */

+ 10 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerContactService.java

@@ -10,6 +10,8 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * 客户联系人信息Service接口
@@ -35,6 +37,14 @@ public interface ICustomerContactService extends IService<CustomerContact> {
      */
     CustomerContactVo selectCustomerContactByCustomerIdAndUserId(Long customerId, Long userId);
 
+    /**
+     * 根据联系人ID批量查询联系人信息
+     *
+     * @param contactIds 联系人ID集合
+     * @return key=contactId, value=CustomerContactVo
+     */
+    Map<Long, CustomerContactVo> selectContactByIds(Set<Long> contactIds);
+
     /**
      * 分页查询客户联系人信息列表
      *

+ 12 - 5
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java

@@ -1,14 +1,12 @@
 package org.dromara.customer.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.customer.domain.CustomerInfo;
 import org.dromara.customer.domain.bo.*;
-import org.dromara.customer.domain.vo.ContractVo;
-import org.dromara.customer.domain.vo.CustomerInfoVo;
-import org.dromara.customer.domain.vo.CustomerListVo;
-import org.dromara.customer.domain.vo.MessagePublishCustomerVo;
+import org.dromara.customer.domain.vo.*;
 
 import java.math.BigDecimal;
 import java.util.Collection;
@@ -130,7 +128,7 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
      * 退回客户到公海
      *
      * @param customerIds 客户ID列表
-     * @param reason 退回原因
+     * @param reason      退回原因
      * @return 更新数量
      */
     int releaseToPool(List<Long> customerIds, String reason);
@@ -195,6 +193,15 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
      */
     CustomerInfoVo selectCustomerByName(String customerName);
 
+    R<CustomerIndexDataVo> customerIndexData();
 
+    Boolean isNeedAffirmOrder(Long customerId);
 
+    /**
+     * 导出模板数据:查询指定数量的客户数据,转换为导入模板格式
+     *
+     * @param limit 查询数量上限
+     * @return 导入模板VO列表
+     */
+    List<CustomerInfoImportVo> queryImportTemplateList(int limit);
 }

+ 8 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerMessageService.java

@@ -59,6 +59,14 @@ public interface ICustomerMessageService extends IService<CustomerMessage> {
      */
     Boolean updateByBo(CustomerMessageBo bo);
 
+    /**
+     * 查询客户最新公告
+     *
+     * @param bo 查询条件(包含customerId)
+     * @return 最新一条客户消息
+     */
+    CustomerMessageVo getNewNotice(CustomerMessageBo bo);
+
     /**
      * 校验并批量删除客户消息信息
      *

+ 39 - 31
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/IPartnerInfoService.java

@@ -1,12 +1,14 @@
 package org.dromara.customer.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.customer.domain.PartnerInfo;
-import org.dromara.customer.domain.vo.CustomerInfoVo;
-import org.dromara.customer.domain.vo.PartnerInfoVo;
 import org.dromara.customer.domain.bo.PartnerInfoBo;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.customer.domain.vo.PartnerInfoIndexDataVo;
+import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.dromara.customer.domain.vo.PartnerManageIndexDataVo;
 
 import java.util.Collection;
 import java.util.List;
@@ -14,7 +16,7 @@ import java.util.Map;
 import java.util.Set;
 
 /**
- * 伙伴商基本信息Service接口
+ * 浼欎即鍟嗗熀鏈�俊鎭疭ervice鎺ュ彛
  *
  * @author LionLi
  * @date 2026-01-21
@@ -22,70 +24,76 @@ import java.util.Set;
 public interface IPartnerInfoService extends IService<PartnerInfo> {
 
     /**
-     * 查询伙伴商基本信息
+     * 鏌ヨ�浼欎即鍟嗗熀鏈�俊鎭?
      *
-     * @param id 主键
-     * @return 伙伴商基本信息
+     * @param id 涓婚敭
+     * @return 浼欎即鍟嗗熀鏈�俊鎭?
      */
     PartnerInfoVo queryById(Long id);
 
     /**
-     * 分页查询伙伴商基本信息列表
+     * 鍒嗛〉鏌ヨ�浼欎即鍟嗗熀鏈�俊鎭�垪琛?
      *
-     * @param bo        查询条件
-     * @param pageQuery 分页参数
-     * @return 伙伴商基本信息分页列表
+     * @param bo        鏌ヨ�鏉′欢
+     * @param pageQuery 鍒嗛〉鍙傛暟
+     * @return 浼欎即鍟嗗熀鏈�俊鎭�垎椤靛垪琛?
      */
     TableDataInfo<PartnerInfoVo> queryPageList(PartnerInfoBo bo, PageQuery pageQuery);
 
     /**
-     * 查询符合条件的伙伴商基本信息列表
+     * 鏌ヨ�绗﹀悎鏉′欢鐨勪紮浼村晢鍩烘湰淇℃伅鍒楄〃
      *
-     * @param bo 查询条件
-     * @return 伙伴商基本信息列表
+     * @param bo 鏌ヨ�鏉′欢
+     * @return 浼欎即鍟嗗熀鏈�俊鎭�垪琛?
      */
     List<PartnerInfoVo> queryList(PartnerInfoBo bo);
 
     /**
-     * 新增伙伴商基本信息
+     * 鏂板�浼欎即鍟嗗熀鏈�俊鎭?
      *
-     * @param bo 伙伴商基本信息
-     * @return 是否新增成功
+     * @param bo 浼欎即鍟嗗熀鏈�俊鎭?
+     * @return 鏄�惁鏂板�鎴愬姛
      */
     Boolean insertByBo(PartnerInfoBo bo);
 
     /**
-     * 修改伙伴商基本信息
+     * 淇�敼浼欎即鍟嗗熀鏈�俊鎭?
      *
-     * @param bo 伙伴商基本信息
-     * @return 是否修改成功
+     * @param bo 浼欎即鍟嗗熀鏈�俊鎭?
+     * @return 鏄�惁淇�敼鎴愬姛
      */
     Boolean updateByBo(PartnerInfoBo bo);
 
     /**
-     * 校验并批量删除伙伴商基本信息信息
+     * 鏍¢獙骞舵壒閲忓垹闄や紮浼村晢鍩烘湰淇℃伅淇℃伅
      *
-     * @param ids     待删除的主键集合
-     * @param isValid 是否进行有效性校验
-     * @return 是否删除成功
+     * @param ids     寰呭垹闄ょ殑涓婚敭闆嗗悎
+     * @param isValid 鏄�惁杩涜�鏈夋晥鎬ф牎楠?
+     * @return 鏄�惁鍒犻櫎鎴愬姛
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
     /**
-     * 获取当前登录用户的伙伴商信息
+     * 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛鐨勪紮浼村晢淇℃伅
      *
-     * @return 伙伴商基本信息
+     * @return 浼欎即鍟嗗熀鏈�俊鎭?
      */
     PartnerInfoVo queryCurrentPartnerInfo();
 
-    /*根据ids查询伙伴商名称*/
+    /**
+     * 根据ids查询伙伴商名称
+     */
     Map<Long, String> selectPartnerNameByIds(Set<Long> ids);
 
     /**
-     * 查询伙伴商名称查询伙伴商信息
+     * 鏌ヨ�浼欎即鍟嗗悕绉版煡璇�紮浼村晢淇℃伅
      *
-     * @param partnerName 主键
-     * @return 伙伴商信息
+     * @param partnerName 涓婚敭
+     * @return 浼欎即鍟嗕俊鎭?
      */
     List<PartnerInfoVo> selectByPartnerName(String partnerName);
+
+    R<PartnerManageIndexDataVo> partnerManageIndexData();
+
+    R<PartnerInfoIndexDataVo> partnerInfoIndexData(Long partnerId);
 }

+ 9 - 2
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierInfoService.java

@@ -6,11 +6,10 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import jakarta.validation.constraints.NotNull;
 import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.bo.*;
-import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.dromara.customer.domain.vo.SupplierInfoImportVo;
 import org.dromara.customer.domain.vo.SupplierInfoVo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
-import org.dromara.customer.domain.vo.SupplierInformationVo;
 
 import java.util.Collection;
 import java.util.List;
@@ -161,4 +160,12 @@ public interface ISupplierInfoService extends IService<SupplierInfo> {
      * @return 是否同步成功
      */
     Boolean syncToTemporaryTable();
+
+    /**
+     * 导出模板数据:查询指定数量的供应商数据,转换为导入模板格式
+     *
+     * @param limit 导出数量
+     * @return 导入模板格式的供应商列表
+     */
+    List<SupplierInfoImportVo> queryImportTemplateList(int limit);
 }

+ 13 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerContactServiceImpl.java

@@ -89,6 +89,17 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
         return baseMapper.selectVoOne(new LambdaQueryWrapper<CustomerContact>().eq(CustomerContact::getCustomerId, customerId).eq(CustomerContact::getUserId, userId).eq(CustomerContact::getDelFlag, '0').last("limit 1"));
     }
 
+    @Override
+    public Map<Long, CustomerContactVo> selectContactByIds(Set<Long> contactIds) {
+        if (contactIds == null || contactIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<CustomerContactVo> list = baseMapper.selectVoByIds(contactIds);
+        return list.stream()
+            .filter(vo -> vo != null && vo.getId() != null)
+            .collect(Collectors.toMap(CustomerContactVo::getId, vo -> vo, (k1, k2) -> k1));
+    }
+
     /**
      * 分页查询客户联系人信息列表
      *
@@ -167,6 +178,8 @@ public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMappe
         lqw.like(StringUtils.isNotBlank(bo.getDeptName()), CustomerContact::getDeptName, bo.getDeptName());
         lqw.like(StringUtils.isNotBlank(bo.getRoleName()), CustomerContact::getRoleName, bo.getRoleName());
         lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), CustomerContact::getPlatformCode, bo.getPlatformCode());
+        lqw.between(ObjectUtil.isNotEmpty(params.get("beginTime")) && ObjectUtil.isNotEmpty(params.get("endTime")),
+            CustomerContact::getCreateTime, params.get("beginTime"), params.get("endTime"));
         // 增加联系人类型查询
         if (StringUtils.isNotBlank(bo.getType())) {
             List<CustomerContactInfo> infoList = contactInfoMapper.selectList(new LambdaQueryWrapper<CustomerContactInfo>()

+ 653 - 61
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.constant.GlobalConstants;
 import org.dromara.common.core.context.PlatformContext;
+import org.dromara.common.core.domain.R;
 import org.dromara.common.core.enums.IsDefault;
 import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.DateUtils;
@@ -31,19 +32,23 @@ import org.dromara.customer.mapper.*;
 import org.dromara.customer.service.ICustomerInfoService;
 import org.dromara.customer.utils.qcc.QccUtils;
 import org.dromara.customer.utils.qcc.domain.CompanyInfoResponse;
+import org.dromara.product.api.RemoteOrderInfoService;
+import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.dto.HotProductRankingDto;
+import org.dromara.product.api.domain.dto.LatestOrderDto;
+import org.dromara.product.api.domain.dto.OrderAmountTrendDto;
+import org.dromara.product.api.domain.dto.OrderStatusCountDto;
 import org.dromara.system.api.*;
 import org.dromara.system.api.domain.bo.RemoteUserBo;
 import org.dromara.system.api.domain.dto.AddressAreaDTO;
-import org.dromara.system.api.domain.vo.RemoteDeptVo;
-import org.dromara.system.api.domain.vo.RemoteComStaffVo;
-import org.dromara.system.api.domain.vo.RemoteDictDataVo;
-import org.dromara.system.api.domain.dto.AddressAreaDTO;
-import org.dromara.system.api.domain.vo.RemoteUserWechatVo;
+import org.dromara.system.api.domain.vo.*;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.time.Duration;
+import java.time.LocalDate;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -85,12 +90,27 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     @DubboReference
     private RemoteComCustomerLevelService remoteComCustomerLevelService;
 
+    @DubboReference
+    private RemoteComCurrencyService remoteComCurrencyService;
+
+    @DubboReference
+    private RemoteComCustomerTypeService remoteComCustomerTypeService;
+
+    @DubboReference
+    private RemoteProductTaxrateService remoteProductTaxrateService;
+
     @DubboReference
     private RemoteDictService remoteDictService;
 
     @DubboReference
     private RemoteAddressAreaService remoteAddressAreaService;
 
+    @DubboReference
+    private RemoteOrderInfoService remoteOrderInfoService;
+
+    @DubboReference
+    private RemoteProductService remoteProductService;
+
     private static final String CUSTOMER_NO_KEY = "customer_info:customer_no";
     private static final String CONTACT_NO_KEY = "customer_contact:contact_no";
 
@@ -447,8 +467,8 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
 
         // === 远程调用获取名称 ===
-        Map<Long, String> comStaffMap = staffIds.isEmpty() ? Collections.emptyMap() : remoteComStaffService.selectStaffNameByIds(comStaffIds);
-        Map<Long, String> comDeptMap = deptIds.isEmpty() ? Collections.emptyMap() : remoteDeptService.selectDeptNameByIds(comDeptIds);
+        Map<Long, String> comStaffMap = comStaffIds.isEmpty() ? Collections.emptyMap() : remoteComStaffService.selectStaffNameByIds(comStaffIds);
+        Map<Long, String> comDeptMap = comDeptIds.isEmpty() ? Collections.emptyMap() : remoteDeptService.selectDeptNameByIds(comDeptIds);
         records.forEach(v -> {
             v.setSalesPersonName(comStaffMap.get(v.getSalesPersonId()));
             v.setServiceStaffName(comStaffMap.get(v.getServiceStaffId()));
@@ -726,9 +746,10 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<CustomerInfo> lqw = Wrappers.lambdaQuery();
         lqw.orderByDesc(CustomerInfo::getId);
-
         // 数据权限过滤:只能查看自己创建的、或者是业务负责人、或者是客服支持的客户
-        if (bo.getCreateBy() != null || bo.getSalesPersonId() != null || bo.getServiceStaffId() != null) {
+        // 超级管理员或租户管理员可查看全部数据
+        if (!LoginHelper.isSuperAdmin() && !LoginHelper.isTenantAdmin()
+            && (bo.getCreateBy() != null || bo.getSalesPersonId() != null || bo.getServiceStaffId() != null)) {
             lqw.and(wrapper -> {
                 boolean first = true;
                 if (bo.getCreateBy() != null) {
@@ -756,7 +777,6 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                 }
             });
         }
-
         lqw.eq(StringUtils.isNotBlank(bo.getCustomerNo()), CustomerInfo::getCustomerNo, bo.getCustomerNo());
         lqw.eq(bo.getBelongCompanyId() != null, CustomerInfo::getBelongCompanyId, bo.getBelongCompanyId());
         lqw.like(StringUtils.isNotBlank(bo.getCompanyName()), CustomerInfo::getCompanyName, bo.getCompanyName());
@@ -857,6 +877,33 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
             String customerNo = entity.getCustomerNo();
 
+            // 团队成员初始化逻辑
+            Set<Long> staffIds = new HashSet<>();
+            if (entity.getSalesPersonId() != null) {
+                staffIds.add(entity.getSalesPersonId());
+            }
+            if (entity.getServiceStaffId() != null) {
+                staffIds.add(entity.getServiceStaffId());
+            }
+
+            // 只有当有相关人员时才进行远程查询和入库
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+
+            // 使用提取的方法处理负责人
+            if (entity.getSalesPersonId() != null) {
+                saveOrUpdateTeamMember(customerNo, entity.getSalesPersonId(),
+                    staffNameMap.get(entity.getSalesPersonId()), "1", 1, 1);
+            }
+
+            // 使用提取的方法处理客服
+            if (entity.getServiceStaffId() != null) {
+                saveOrUpdateTeamMember(customerNo, entity.getServiceStaffId(),
+                    staffNameMap.get(entity.getServiceStaffId()), "3", 0, 1);
+            }
+
             /*新增客户时给每个客户创建自己的组织架构*/
             RemoteDeptVo remoteDeptVo = new RemoteDeptVo();
             remoteDeptVo.setParentId(0L);
@@ -964,6 +1011,95 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
     }
 
+    /**
+     * 保存或更新团队成员信息
+     * 如果成员已存在但被删除,则恢复;否则新增
+     *
+     * @param objectNo      客户编号
+     * @param userNo        人员ID
+     * @param realName      人员姓名
+     * @param roleCode      角色编码 (1:负责人, 2:客服)
+     * @param izManager     是否主管
+     * @param updateAccredit 授权更新标识
+     */
+    /**
+     * 保存或更新团队成员信息(公用方法)
+     * 确保一个客户的团队中只能有一个 roleCode=1 的负责人和一个 roleCode=2 的客服支持
+     *
+     * @param objectNo       客户编号
+     * @param userNo         人员ID
+     * @param realName       人员姓名
+     * @param roleCode       角色编码 (1:负责人, 2:客服)
+     * @param izManager      是否主管
+     * @param updateAccredit 授权更新标识
+     */
+    public void saveOrUpdateTeamMember(String objectNo, Long userNo, String realName,
+                                       String roleCode, Integer izManager, Integer updateAccredit) {
+        if (userNo == null || StringUtils.isBlank(objectNo)) {
+            return;
+        }
+
+        // 1. 查找该客户下指定角色的现有成员(包括已删除的)
+        TeamMemberVo existing = teamMemberMapper.selectByObjectNoAndRoleCodeWithDeleted(objectNo, roleCode);
+
+        if (existing != null && !existing.getUserNo().equals(userNo)) {
+            // 2. 如果存在不同的人员占据该角色,先将其软删除或更新状态
+            teamMemberMapper.update(null, new LambdaUpdateWrapper<TeamMember>()
+                .set(TeamMember::getIsDelete, 1)
+                .eq(TeamMember::getId, existing.getId()));
+        }
+
+        // 3. 查找新人员是否已在该客户团队中(任意角色)
+        TeamMemberVo existingUser = teamMemberMapper.selectByObjectNoAndUserNoWithDeleted(objectNo, userNo);
+
+        if (existingUser != null) {
+            // 如果角色相同,恢复并更新
+            if (Objects.equals(existingUser.getRoleCode(), roleCode)) {
+                teamMemberMapper.restoreMemberById(
+                    existingUser.getId(),
+                    userNo,
+                    realName,
+                    roleCode,
+                    updateAccredit,
+                    izManager,
+                    LoginHelper.getUserId(),
+                    LoginHelper.getDeptId(),
+                    PlatformContext.getPlatform()
+                );
+            } else {
+                // 角色不同(如同一个人既是负责人又是客服),新增一条记录
+                TeamMember member = new TeamMember();
+                member.setDataType(12);
+                member.setObjectNo(objectNo);
+                member.setUserNo(userNo);
+                member.setRealName(realName);
+                member.setRoleCode(roleCode);
+                member.setIzManager(izManager);
+                member.setUpdateAccredit(updateAccredit);
+                member.setPlatformCode(PlatformContext.getPlatform());
+                member.setCreateUserId(LoginHelper.getUserId());
+                member.setCreateOrgId(LoginHelper.getDeptId());
+                member.setIsDelete(0);
+                teamMemberMapper.insert(member);
+            }
+        } else {
+            // 5. 如果人员不存在,执行新增
+            TeamMember member = new TeamMember();
+            member.setDataType(12); // 12 代表客户类型
+            member.setObjectNo(objectNo);
+            member.setUserNo(userNo);
+            member.setRealName(realName);
+            member.setRoleCode(roleCode);
+            member.setIzManager(izManager);
+            member.setUpdateAccredit(updateAccredit);
+            member.setPlatformCode(PlatformContext.getPlatform());
+            member.setCreateUserId(LoginHelper.getUserId());
+            member.setCreateOrgId(LoginHelper.getDeptId());
+            member.setIsDelete(0);
+            teamMemberMapper.insert(member);
+        }
+    }
+
     /**
      * 修改客户信息
      *
@@ -1091,6 +1227,9 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                 if (null == salesInfoVo.getCreditManagementId()) {
                     throw new ServiceException("ERP销售人员信用等级不能为空");
                 }
+                if (null == salesInfoVo.getOrderAudit()) {
+                    throw new ServiceException("ERP销售人员订单审核方式不能为空");
+                }
             }
         }
         return baseMapper.update(null,
@@ -1543,24 +1682,23 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             return 0;
         }
 
-        if (salesPersonId == null ) {
-            log.warn("转移业务人员失败,业务人员 ID 为空");
-            throw new ServiceException("业务人员不能为空");
-        }
-
         try {
+            // 获取新业务员的姓名
+            Map<Long, String> staffMap = remoteComStaffService.selectStaffNameByIds(Collections.singleton(salesPersonId));
+            String realName = staffMap.get(salesPersonId);
+
             List<CustomerInfo> updateList = new ArrayList<>();
-            CustomerInfo customerInfo = null;
             for (Long customerId : customerIds) {
-                if (customerId == null) {
-                    continue;
-                }
+                if (customerId == null) continue;
 
-                customerInfo = baseMapper.selectById(customerId);
+                CustomerInfo customerInfo = baseMapper.selectById(customerId);
                 if (customerInfo != null) {
                     customerInfo.setSalesPersonId(salesPersonId);
                     customerInfo.setBelongingDepartmentId(deptId);
                     updateList.add(customerInfo);
+
+                    // 同步更新团队成员:角色 1 为负责人
+                    saveOrUpdateTeamMember(customerInfo.getCustomerNo(), salesPersonId, realName, "1", 1, 1);
                 } else {
                     log.warn("客户 ID: {} 不存在,跳过更新", customerId);
                 }
@@ -1573,17 +1711,12 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                         updateList.size(), salesPersonId, deptId);
                     return updateList.size();
                 } else {
-                    log.error("批量更新客户信息失败");
                     throw new ServiceException("批量更新客户信息失败");
                 }
             }
-
-            log.info("没有需要更新的客户销售信息");
             return 0;
-
         } catch (Exception e) {
-            log.error("转移业务人员失败,客户 IDs: {}, 业务员 ID: {}, 部门 ID: {}, 错误:{}",
-                customerIds, salesPersonId, deptId, e.getMessage(), e);
+            log.error("转移业务人员失败,错误:{}", e.getMessage(), e);
             throw new ServiceException("转移业务人员失败:" + e.getMessage());
         }
     }
@@ -1591,28 +1724,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int transferServiceStaff(List<Long> customerIds, Long serviceStaffId) {
-        if (CollUtil.isEmpty(customerIds)) {
-            log.warn("转移客服人员失败,客户 ID 列表为空");
+        if (CollUtil.isEmpty(customerIds) || serviceStaffId == null) {
             return 0;
         }
 
-        if (serviceStaffId == null) {
-            log.warn("转移客服人员失败,客服人员 ID 为空");
-            throw new ServiceException("客服人员和不能为空");
-        }
-
         try {
+            // 获取新客服的姓名
+            Map<Long, String> staffMap = remoteComStaffService.selectStaffNameByIds(Collections.singleton(serviceStaffId));
+            String realName = staffMap.get(serviceStaffId);
+
             List<CustomerInfo> updateList = new ArrayList<>();
-            CustomerInfo customerInfo = null;
             for (Long customerId : customerIds) {
-                if (customerId == null) {
-                    continue;
-                }
+                if (customerId == null) continue;
 
-                customerInfo = baseMapper.selectById(customerId);
+                CustomerInfo customerInfo = baseMapper.selectById(customerId);
                 if (customerInfo != null) {
                     customerInfo.setServiceStaffId(serviceStaffId);
                     updateList.add(customerInfo);
+
+                    // 同步更新团队成员:角色 3 为客服支持
+                    saveOrUpdateTeamMember(customerInfo.getCustomerNo(), serviceStaffId, realName, "3", 0, 1);
                 } else {
                     log.warn("客户 ID: {} 不存在,跳过更新", customerId);
                 }
@@ -1625,25 +1756,14 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                         updateList.size(), serviceStaffId);
                     return updateList.size();
                 } else {
-                    log.error("批量更新客户信息失败");
                     throw new ServiceException("批量更新客户信息失败");
                 }
             }
-
-            log.info("没有需要更新的客户销售信息");
             return 0;
-
         } catch (Exception e) {
-            log.error("转移客服人员失败,客户 IDs: {}, 客服人员 ID: {},  错误:{}",
-                customerIds, serviceStaffId, e.getMessage(), e);
+            log.error("转移客服人员失败,错误:{}", e.getMessage(), e);
             throw new ServiceException("转移客服人员失败:" + e.getMessage());
         }
-
-        // 直接进行批量更新
-//        return baseMapper.update(null, new LambdaUpdateWrapper<CustomerInfo>()
-//            .set(CustomerInfo::getServiceStaffId, serviceStaffId)
-//            .in(CustomerInfo::getId, customerIds)
-//        );
     }
 
     /**
@@ -1660,6 +1780,7 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
             bo.setId(add.getId());
+
             CustomerSalesInfoBo customerSalesInfoBo = bo.getCustomerSalesInfoBo();
             customerSalesInfoBo.setCustomerId(add.getId());
             CustomerSalesInfo bean = BeanUtil.toBean(customerSalesInfoBo, CustomerSalesInfo.class);
@@ -1669,6 +1790,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
             customerBusinessInfo.setBusinessCustomerName(bo.getBusinessCustomerName());
             customerBusinessInfo.setSocialCreditCode(bo.getSocialCreditCode());
             customerBusinessInfoMapper.insert(customerBusinessInfo);
+            // 将业务员和客服加入团队成员
+            Set<Long> staffIds = new HashSet<>();
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                staffIds.add(bo.getSalesPersonId());
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                staffIds.add(bo.getServiceStaffId());
+            }
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                saveOrUpdateTeamMember(add.getCustomerNo(), bo.getSalesPersonId(),
+                    staffNameMap.get(bo.getSalesPersonId()), "1", 1, 1);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                saveOrUpdateTeamMember(add.getCustomerNo(), bo.getServiceStaffId(),
+                    staffNameMap.get(bo.getServiceStaffId()), "3", 0, 1);
+            }
         }
         return flag;
     }
@@ -1701,6 +1842,26 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
                 customerBusinessInfo.setSocialCreditCode(bo.getSocialCreditCode());
                 customerBusinessInfoMapper.updateById(customerBusinessInfo);
             }
+            // 将业务员和客服加入团队成员
+            Set<Long> staffIds = new HashSet<>();
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                staffIds.add(bo.getSalesPersonId());
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                staffIds.add(bo.getServiceStaffId());
+            }
+            Map<Long, String> staffNameMap = Collections.emptyMap();
+            if (!staffIds.isEmpty()) {
+                staffNameMap = remoteComStaffService.selectStaffNameByIds(staffIds);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getSalesPersonId())) {
+                saveOrUpdateTeamMember(update.getCustomerNo(), bo.getSalesPersonId(),
+                    staffNameMap.get(bo.getSalesPersonId()), "1", 1, 1);
+            }
+            if (ObjectUtils.isNotEmpty(bo.getServiceStaffId())) {
+                saveOrUpdateTeamMember(update.getCustomerNo(), bo.getServiceStaffId(),
+                    staffNameMap.get(bo.getServiceStaffId()), "3", 0, 1);
+            }
         }
 
         return flag;
@@ -1745,17 +1906,35 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
         }
 
         if (existing != null) {
-            teamMemberMapper.restoreMemberById(
-                existing.getId(),
-                userNo,
-                realName,
-                roleCode,
-                updateAccredit,
-                izManager,
-                LoginHelper.getUserId(),
-                LoginHelper.getDeptId(),
-                PlatformContext.getPlatform()
-            );
+            // 如果角色相同,恢复并更新
+            if (Objects.equals(existing.getRoleCode(), roleCode)) {
+                teamMemberMapper.restoreMemberById(
+                    existing.getId(),
+                    userNo,
+                    realName,
+                    roleCode,
+                    updateAccredit,
+                    izManager,
+                    LoginHelper.getUserId(),
+                    LoginHelper.getDeptId(),
+                    PlatformContext.getPlatform()
+                );
+            } else {
+                // 角色不同(如同一个人既是负责人又是客服),新增一条记录
+                TeamMember member = new TeamMember();
+                member.setDataType(12);
+                member.setObjectNo(objectNo);
+                member.setUserNo(userNo);
+                member.setRealName(realName);
+                member.setRoleCode(roleCode);
+                member.setIzManager(izManager);
+                member.setUpdateAccredit(updateAccredit);
+                member.setPlatformCode(PlatformContext.getPlatform());
+                member.setCreateUserId(LoginHelper.getUserId());
+                member.setCreateOrgId(LoginHelper.getDeptId());
+                member.setIsDelete(0);
+                teamMemberMapper.insert(member);
+            }
         } else {
             TeamMember member = new TeamMember();
             member.setDataType(12);
@@ -1794,4 +1973,417 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     public CustomerInfoVo selectCustomerByName(String customerName) {
         return baseMapper.selectVoOne(new LambdaQueryWrapper<CustomerInfo>().eq(CustomerInfo::getCustomerName, customerName));
     }
+
+    @Override
+    public R<CustomerIndexDataVo> customerIndexData() {
+        CustomerIndexDataVo vo = new CustomerIndexDataVo();
+
+        // 1. 总客户数
+        vo.setTotalCustomers(baseMapper.selectCount(null));
+
+        // 2. 订单统计
+        OrderStatusCountDto orderStatusCount = remoteOrderInfoService.getOrderStatusCount(null);
+        vo.setTotalOrders(orderStatusCount.getOrderCount());
+
+        // 3. 商品总量
+        vo.setTotalProducts(remoteProductService.getTotalProductCount());
+
+        // 4. 本月营收(从订单金额趋势汇总)
+        List<OrderAmountTrendDto> orderAmountTrend = remoteOrderInfoService.getOrderAmountTrend(null);
+        BigDecimal monthlyRevenue = orderAmountTrend.stream()
+            .map(OrderAmountTrendDto::getAmount)
+            .filter(Objects::nonNull)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        vo.setMonthlyRevenue(monthlyRevenue);
+
+        // 5. 最近七天客户趋势
+        LocalDate today = LocalDate.now();
+        LocalDate sevenDaysAgo = today.minusDays(6);
+        List<CustomerInfo> recentCustomers = baseMapper.selectList(
+            new LambdaQueryWrapper<CustomerInfo>()
+                .ge(CustomerInfo::getCreateTime, java.sql.Date.valueOf(sevenDaysAgo))
+                .le(CustomerInfo::getCreateTime, java.sql.Date.valueOf(today))
+        );
+        Map<LocalDate, Long> dailyCustomerMap = new LinkedHashMap<>();
+        LocalDate cursor = sevenDaysAgo;
+        while (!cursor.isAfter(today)) {
+            dailyCustomerMap.put(cursor, 0L);
+            cursor = cursor.plusDays(1);
+        }
+        for (CustomerInfo c : recentCustomers) {
+            if (c.getCreateTime() != null) {
+                LocalDate createDate = c.getCreateTime().toInstant()
+                    .atZone(ZoneId.systemDefault()).toLocalDate();
+                dailyCustomerMap.merge(createDate, 1L, Long::sum);
+            }
+        }
+        List<String> weekDayNames = Arrays.asList("周一", "周二", "周三", "周四", "周五", "周六", "周日");
+        List<CustomerIndexDataVo.TrendItem> customerTrend = new ArrayList<>();
+        int idx = 0;
+        for (Map.Entry<LocalDate, Long> entry : dailyCustomerMap.entrySet()) {
+            CustomerIndexDataVo.TrendItem item = new CustomerIndexDataVo.TrendItem();
+            // 使用星期几作为标签,与前端保持一致
+            item.setDate(weekDayNames.get(idx % 7));
+            item.setValue(BigDecimal.valueOf(entry.getValue()));
+            customerTrend.add(item);
+            idx++;
+        }
+        vo.setCustomerTrend(customerTrend);
+
+        // 6. 本月订单金额趋势(转换DTO->VO)
+        List<CustomerIndexDataVo.TrendItem> orderTrendItems = orderAmountTrend.stream().map(dto -> {
+            CustomerIndexDataVo.TrendItem item = new CustomerIndexDataVo.TrendItem();
+            item.setDate(dto.getDate());
+            item.setValue(dto.getAmount());
+            return item;
+        }).collect(Collectors.toList());
+        vo.setOrderAmountTrend(orderTrendItems);
+
+        // 7. 客户类型分布
+        List<CustomerInfo> allCustomers = baseMapper.selectList(
+            new LambdaQueryWrapper<CustomerInfo>()
+                .isNotNull(CustomerInfo::getCustomerTypeId)
+                .select(CustomerInfo::getCustomerTypeId)
+        );
+        Map<Long, Long> typeCountMap = allCustomers.stream()
+            .filter(c -> c.getCustomerTypeId() != null)
+            .collect(Collectors.groupingBy(CustomerInfo::getCustomerTypeId, Collectors.counting()));
+
+        // 查询字典获取类型名称
+        List<RemoteDictDataVo> enterpriseTypeDicts = remoteDictService.selectDictDataByType("Q0001");
+        Map<String, String> dictMap = CollUtil.emptyIfNull(enterpriseTypeDicts).stream()
+            .collect(Collectors.toMap(RemoteDictDataVo::getDictValue, RemoteDictDataVo::getDictLabel, (k1, k2) -> k1));
+
+        List<CustomerIndexDataVo.TypeDistribution> typeDistributions = typeCountMap.entrySet().stream()
+            .map(entry -> {
+                CustomerIndexDataVo.TypeDistribution td = new CustomerIndexDataVo.TypeDistribution();
+                String typeName = dictMap.get(String.valueOf(entry.getKey()));
+                td.setName(typeName != null ? typeName : "其他");
+                td.setValue(entry.getValue());
+                return td;
+            }).collect(Collectors.toList());
+        vo.setCustomerTypeDistribution(typeDistributions);
+
+        // 8. 最新订单明细
+        List<LatestOrderDto> latestOrders = remoteOrderInfoService.getLatestOrders(null, 10);
+        List<CustomerIndexDataVo.LatestOrder> orderList = latestOrders.stream().map(dto -> {
+            CustomerIndexDataVo.LatestOrder order = new CustomerIndexDataVo.LatestOrder();
+            order.setOrderNo(dto.getOrderNo());
+            order.setCustomer(dto.getCustomerName());
+            order.setProduct(dto.getProductName());
+            order.setAmount(dto.getAmount());
+            order.setStatus(dto.getOrderStatus());
+            order.setDate(dto.getOrderTime());
+            return order;
+        }).collect(Collectors.toList());
+        vo.setLatestOrders(orderList);
+
+        // 9. 热销商品排行榜
+        List<HotProductRankingDto> hotProductRankings = remoteOrderInfoService.getHotProductRankings(null, 6);
+        // 计算最大销量用于百分比
+        long maxSales = hotProductRankings.stream()
+            .mapToLong(HotProductRankingDto::getSalesCount)
+            .max().orElse(1L);
+        List<CustomerIndexDataVo.HotProduct> hotProducts = hotProductRankings.stream().map(dto -> {
+            CustomerIndexDataVo.HotProduct hp = new CustomerIndexDataVo.HotProduct();
+            hp.setName(dto.getProductName());
+            hp.setSales(dto.getSalesCount());
+            // 百分比 = 当前销量 / 最大销量 * 100
+            int percentage = maxSales > 0
+                ? (int) Math.round(dto.getSalesCount() * 100.0 / maxSales)
+                : 0;
+            hp.setPercentage(percentage);
+            return hp;
+        }).collect(Collectors.toList());
+        vo.setHotProductRankings(hotProducts);
+
+        return R.ok(vo);
+    }
+
+    //是否需要确认订单
+    @Override
+    public Boolean isNeedAffirmOrder(Long customerId) {
+        boolean affirmFlag = false;
+        CustomerInfoVo customerInfoVo = baseMapper.selectVoById(customerId);
+        if (ObjectUtils.isNotEmpty(customerInfoVo)) {
+            CustomerSalesInfoVo salesInfoVo = customerSalesInfoMapper.selectVoOne(new LambdaQueryWrapper<CustomerSalesInfo>().eq(CustomerSalesInfo::getCustomerId, customerInfoVo.getId()).last("LIMIT 1"));
+            if (ObjectUtils.isNotEmpty(salesInfoVo) && ObjectUtils.isNotEmpty(salesInfoVo.getOrderAudit())) {
+                if ("1".equals(salesInfoVo.getOrderAudit())) {//下单后需要客服确认
+                    affirmFlag = true;
+                }
+            }
+        }
+        return affirmFlag;
+    }
+
+    /**
+     * 导出模板数据:查询指定数量的客户数据,转换为导入模板格式
+     */
+    @Override
+    public List<CustomerInfoImportVo> queryImportTemplateList(int limit) {
+        List<CustomerInfoVo> list;
+
+        if (limit <= 0) {
+            // 导出全部
+            list = baseMapper.selectVoList(new LambdaQueryWrapper<>());
+        } else {
+            // 1. 分页查询客户主表数据(带销售信息)
+            PageQuery pageQuery = new PageQuery();
+            pageQuery.setPageNum(1);
+            pageQuery.setPageSize(limit);
+            TableDataInfo<CustomerInfoVo> pageResult = queryPageList(new CustomerInfoBo(), pageQuery);
+            list = pageResult.getRows();
+        }
+
+        if (CollUtil.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+
+        // 2. 收集所有需要远程查询的ID
+        Set<Long> companyIds = new HashSet<>();
+        Set<Long> customerLevelIds = new HashSet<>();
+        Set<Long> customerTypeIds = new HashSet<>();
+        Set<Long> industryCategoryIds = new HashSet<>();
+        Set<Long> enterpriseScaleIds = new HashSet<>();
+        Set<Long> comStaffIds = new HashSet<>();
+        Set<Long> creditLevelIds = new HashSet<>();
+        Set<Long> dealCurrencyIds = new HashSet<>();
+        Set<Long> rateIds = new HashSet<>();
+        Set<Long> erpStaffIds = new HashSet<>();
+
+        for (CustomerInfoVo vo : list) {
+            if (vo.getBelongCompanyId() != null) companyIds.add(vo.getBelongCompanyId());
+            if (vo.getCustomerLevelId() != null) customerLevelIds.add(vo.getCustomerLevelId());
+            if (vo.getCustomerTypeId() != null) customerTypeIds.add(vo.getCustomerTypeId());
+            if (vo.getIndustryCategoryId() != null) industryCategoryIds.add(vo.getIndustryCategoryId());
+            if (vo.getEnterpriseScaleId() != null) enterpriseScaleIds.add(vo.getEnterpriseScaleId());
+            if (vo.getSalesPersonId() != null) comStaffIds.add(vo.getSalesPersonId());
+            if (vo.getServiceStaffId() != null) comStaffIds.add(vo.getServiceStaffId());
+
+            CustomerSalesInfoVo salesVo = vo.getCustomerSalesInfoVo();
+            if (salesVo != null) {
+                if (salesVo.getCreditLevelId() != null) creditLevelIds.add(salesVo.getCreditLevelId());
+                if (salesVo.getDealCurrencyId() != null) dealCurrencyIds.add(salesVo.getDealCurrencyId());
+                if (salesVo.getRateId() != null) rateIds.add(salesVo.getRateId());
+                if (salesVo.getSalesPersonId() != null) erpStaffIds.add(salesVo.getSalesPersonId());
+                if (salesVo.getServiceStaffId() != null) erpStaffIds.add(salesVo.getServiceStaffId());
+            }
+        }
+
+        // 3. 批量查询远程服务获取名称和编码
+        // 公司:通过 selectCompanyList 全量加载后构建Map(因无批量ID查询方法)
+        Map<Long, RemoteComCompanyVo> companyMap = new HashMap<>();
+        if (!companyIds.isEmpty()) {
+            List<RemoteComCompanyVo> companyList = remoteComCompanyService.selectCompanyList();
+            for (RemoteComCompanyVo vo : companyList) {
+                if (companyIds.contains(vo.getId())) {
+                    companyMap.put(vo.getId(), vo);
+                }
+            }
+        }
+
+        // 客户等级:通过ID批量查询
+        Map<Long, String> customerLevelNameMap = customerLevelIds.isEmpty()
+            ? Collections.emptyMap()
+            : remoteComCustomerLevelService.selectCustomerLevelNameByIds(customerLevelIds);
+        Map<Long, RemoteComCustomerLevelVo> customerLevelMap = new HashMap<>();
+        if (!customerLevelIds.isEmpty()) {
+            List<RemoteComCustomerLevelVo> levelList = remoteComCustomerLevelService.selectCustomerLevelList();
+            for (RemoteComCustomerLevelVo vo : levelList) {
+                if (customerLevelIds.contains(vo.getId())) {
+                    customerLevelMap.put(vo.getId(), vo);
+                }
+            }
+        }
+
+        // 客户类型
+        Map<Long, RemoteComCustomerTypeVo> customerTypeMap = new HashMap<>();
+        if (!customerTypeIds.isEmpty()) {
+            List<RemoteComCustomerTypeVo> typeList = remoteComCustomerTypeService.selectCustomerTypeByIds(customerTypeIds);
+            for (RemoteComCustomerTypeVo vo : typeList) {
+                customerTypeMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 行业类别
+        Map<Long, IndustryCategoryVo> industryCategoryMap = new HashMap<>();
+        if (!industryCategoryIds.isEmpty()) {
+            List<IndustryCategoryVo> industryList = industryCategoryMapper.selectVoByIds(industryCategoryIds);
+            for (IndustryCategoryVo vo : industryList) {
+                industryCategoryMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 企业规模
+        Map<Long, EnterpriseScaleVo> enterpriseScaleMap = new HashMap<>();
+        if (!enterpriseScaleIds.isEmpty()) {
+            List<EnterpriseScaleVo> scaleList = enterpriseScaleMapper.selectVoByIds(enterpriseScaleIds);
+            for (EnterpriseScaleVo vo : scaleList) {
+                enterpriseScaleMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 系统人员(ComStaff)
+        Map<Long, RemoteComStaffVo> comStaffMap = new HashMap<>();
+        if (!comStaffIds.isEmpty()) {
+            List<RemoteComStaffVo> staffList = remoteComStaffService.selectStaffByIds(comStaffIds);
+            for (RemoteComStaffVo vo : staffList) {
+                comStaffMap.put(vo.getStaffId(), vo);
+            }
+        }
+
+        // 信用等级
+        Map<Long, String> creditLevelNameMap = creditLevelIds.isEmpty()
+            ? Collections.emptyMap()
+            : remoteCreditLevelService.selectCreditLevelNameByIds(creditLevelIds);
+
+        // 交易币别
+        Map<Long, RemoteComCurrencyVo> currencyMap = new HashMap<>();
+        if (!dealCurrencyIds.isEmpty()) {
+            List<RemoteComCurrencyVo> currencyList = remoteComCurrencyService.selectCurrencyByIds(dealCurrencyIds);
+            for (RemoteComCurrencyVo vo : currencyList) {
+                currencyMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 税码
+        Map<Long, RemoteProductTaxrateVo> taxrateMap = new HashMap<>();
+        if (!rateIds.isEmpty()) {
+            List<RemoteProductTaxrateVo> taxrateList = remoteProductTaxrateService.selectTaxrateByIds(rateIds);
+            for (RemoteProductTaxrateVo vo : taxrateList) {
+                taxrateMap.put(vo.getId(), vo);
+            }
+        }
+
+        // ERP人员
+        Map<Long, String> erpStaffNameMap = erpStaffIds.isEmpty()
+            ? Collections.emptyMap()
+            : remoteErpStaffService.selectStaffNameByIds(erpStaffIds);
+
+        // 信用等级名称 → 数字映射(用于导出)
+        Map<String, String> creditLevelReverseMap = Map.of(
+            "A", "0", "B", "1", "C", "2", "D", "3", "E", "4", "F", "5", "G", "6"
+        );
+
+        // 客户来源字典 (customer_source) - dictValue → dictLabel
+        Map<String, String> customerSourceDictMap = new HashMap<>();
+        List<RemoteDictDataVo> customerSourceDicts = remoteDictService.selectDictDataByType("customer_source");
+        CollUtil.emptyIfNull(customerSourceDicts).forEach(d -> customerSourceDictMap.put(d.getDictValue(), d.getDictLabel()));
+
+        // 销售通路字典 (sell_channel) - dictValue → dictLabel
+        Map<String, String> sellChannelDictMap = new HashMap<>();
+        List<RemoteDictDataVo> sellChannelDicts = remoteDictService.selectDictDataByType("sell_channel");
+        CollUtil.emptyIfNull(sellChannelDicts).forEach(d -> sellChannelDictMap.put(d.getDictValue(), d.getDictLabel()));
+
+        // 4. 构建导出VO列表
+        List<CustomerInfoImportVo> exportList = new ArrayList<>();
+        for (CustomerInfoVo vo : list) {
+            CustomerInfoImportVo importVo = new CustomerInfoImportVo();
+
+            // 公司信息
+            RemoteComCompanyVo companyVo = companyMap.get(vo.getBelongCompanyId());
+            importVo.setCompanyCode(companyVo != null ? companyVo.getCompanyCode() : null);
+            importVo.setCompanyName(companyVo != null ? companyVo.getCompanyName() : vo.getCompanyName());
+
+            // 基本信息
+            importVo.setCustomerNo(vo.getCustomerNo());
+            importVo.setCustomerName(vo.getCustomerName());
+            importVo.setBusinessCustomerName(vo.getBusinessCustomerName());
+            importVo.setShortName(vo.getShortName());
+            importVo.setSocialCreditCode(vo.getSocialCreditCode());
+
+            // 地址信息
+            importVo.setProvinceNo(vo.getRegProvincialNo());
+            importVo.setCityNo(vo.getRegCityNo());
+            importVo.setAreaNo(vo.getRegCountyNo());
+            importVo.setAddress(vo.getAddress());
+
+            // 客户等级
+            RemoteComCustomerLevelVo levelVo = customerLevelMap.get(vo.getCustomerLevelId());
+            importVo.setCustomerLevelNo(levelVo != null ? levelVo.getLevelCode() : null);
+            importVo.setCustomerLevelName(levelVo != null ? levelVo.getLevelName() : customerLevelNameMap.get(vo.getCustomerLevelId()));
+
+            // 客户类型
+            RemoteComCustomerTypeVo typeVo = customerTypeMap.get(vo.getCustomerTypeId());
+            importVo.setCustomerTypeNo(typeVo != null ? typeVo.getTypeCode() : null);
+            importVo.setCustomerTypeName(typeVo != null ? typeVo.getTypeName() : null);
+
+            // 行业类别
+            IndustryCategoryVo industryVo = industryCategoryMap.get(vo.getIndustryCategoryId());
+            importVo.setIndustryCategoryNo(industryVo != null ? industryVo.getIndustryCode() : null);
+            importVo.setIndustryCategory(industryVo != null ? industryVo.getIndustryCategoryName() : vo.getIndustryCategory());
+
+            // 企业规模
+            EnterpriseScaleVo scaleVo = enterpriseScaleMap.get(vo.getEnterpriseScaleId());
+            importVo.setEnterpriseScaleNo(scaleVo != null ? scaleVo.getEnterpriseScaleCode() : null);
+            importVo.setEnterpriseScale(scaleVo != null ? scaleVo.getEnterpriseScaleName() : null);
+
+            // 系统人员(业务负责人)
+            RemoteComStaffVo xtSales = comStaffMap.get(vo.getSalesPersonId());
+            importVo.setXtSalesPersonNo(xtSales != null ? xtSales.getStaffCode() : null);
+            importVo.setXtSalesPersonName(xtSales != null ? xtSales.getStaffName() : vo.getSalesPersonName());
+
+            // 系统人员(客服支持)
+            RemoteComStaffVo xtService = comStaffMap.get(vo.getServiceStaffId());
+            importVo.setXtServiceStaffNo(xtService != null ? xtService.getStaffCode() : null);
+            importVo.setXtServiceStaffName(xtService != null ? xtService.getStaffName() : vo.getServiceStaffName());
+
+            // 销售信息
+            CustomerSalesInfoVo salesVo = vo.getCustomerSalesInfoVo();
+            if (salesVo != null) {
+                // 客户来源(从字典获取,格式:编码,名称,如"0001,主动来电")
+                String customerSourceLabel = customerSourceDictMap.get(salesVo.getCustomerSource());
+                if (StringUtils.isNotBlank(customerSourceLabel)) {
+                    String[] parts = customerSourceLabel.split(",");
+                    importVo.setSourceNo(parts.length > 0 ? parts[0].trim() : null);
+                    importVo.setSourceName(parts.length > 1 ? parts[1].trim() : customerSourceLabel);
+                }
+                // 销售通路(从字典获取,格式:编码,名称)
+                String sellChannelLabel = sellChannelDictMap.get(salesVo.getSellChannel());
+                if (StringUtils.isNotBlank(sellChannelLabel)) {
+                    String[] parts = sellChannelLabel.split(",");
+                    importVo.setSellChannelNo(parts.length > 0 ? parts[0].trim() : null);
+                    importVo.setSellChannel(parts.length > 1 ? parts[1].trim() : sellChannelLabel);
+                }
+                // 单价含税
+                importVo.setUnitPrice(salesVo.getUnitPrice());
+                // 账款额度超限
+                importVo.setCreditLimit(salesVo.getCreditLimit());
+                // 额度超期
+                importVo.setCreditTimeLimit(salesVo.getCreditTimeLimit());
+                // 账款归属
+                importVo.setAccountBelong(salesVo.getAccountBelong());
+
+                // ERP 业务人员(salesPersonNo 在导入时按 staffName 查询)
+                String erpSalesName = erpStaffNameMap.get(salesVo.getSalesPersonId());
+                importVo.setSalesPersonNo(erpSalesName != null ? erpSalesName : salesVo.getSalesPerson());
+                importVo.setSalesPersonName(erpSalesName != null ? erpSalesName : salesVo.getSalesPerson());
+
+                // ERP 业务助理(serviceStaffNo 在导入时按 staffName 查询)
+                String erpServiceName = erpStaffNameMap.get(salesVo.getServiceStaffId());
+                importVo.setServiceStaffNo(erpServiceName != null ? erpServiceName : salesVo.getServiceStaff());
+                importVo.setServiceStaffName(erpServiceName != null ? erpServiceName : salesVo.getServiceStaff());
+
+                // 信用等级:将名称映射回数字
+                String creditLevelName = creditLevelNameMap.get(salesVo.getCreditLevelId());
+                importVo.setCreditLevel(creditLevelName != null ? creditLevelReverseMap.getOrDefault(creditLevelName, creditLevelName) : null);
+
+                // 交易币别:导出 currencyCode
+                RemoteComCurrencyVo currencyVo = currencyMap.get(salesVo.getDealCurrencyId());
+                importVo.setDealCurrency(currencyVo != null ? currencyVo.getCurrencyCode() : null);
+
+                // 税码
+                RemoteProductTaxrateVo taxrateVo = taxrateMap.get(salesVo.getRateId());
+                importVo.setRateName(taxrateVo != null ? taxrateVo.getTaxrateNo() : null);
+            }
+
+            // 销售开票类型(直接从 CustomerInfoVo 获取)
+            importVo.setSellInvoiceTypeNo(vo.getSellInvoiceTypeNo());
+            importVo.setSellInvoiceType(vo.getSellInvoiceType());
+
+            exportList.add(importVo);
+        }
+
+        return exportList;
+    }
 }

+ 16 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerMessageServiceImpl.java

@@ -86,6 +86,22 @@ public class CustomerMessageServiceImpl extends ServiceImpl<CustomerMessageMappe
         return lqw;
     }
 
+    /**
+     * 查询客户最新公告
+     *
+     * @param bo 查询条件(包含customerId)
+     * @return 最新一条客户消息
+     */
+    @Override
+    public CustomerMessageVo getNewNotice(CustomerMessageBo bo) {
+        LambdaQueryWrapper<CustomerMessage> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getCustomerId() != null, CustomerMessage::getCustomerId, bo.getCustomerId());
+        lqw.eq(CustomerMessage::getStatus, "0");
+        lqw.orderByDesc(CustomerMessage::getCreateTime);
+        lqw.last("limit 1");
+        return baseMapper.selectVoOne(lqw);
+    }
+
     /**
      * 新增客户消息
      *

+ 235 - 15
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/PartnerInfoServiceImpl.java

@@ -1,29 +1,44 @@
 package org.dromara.customer.service.impl;
 
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.dromara.common.core.utils.MapstructUtils;
-import org.dromara.common.core.utils.StringUtils;
-import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.common.mybatis.core.page.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.dromara.customer.domain.CustomerInfo;
-import org.dromara.customer.domain.SupplierInfo;
-import org.dromara.customer.domain.vo.CustomerInfoVo;
-import org.springframework.stereotype.Service;
-import org.dromara.customer.domain.bo.PartnerInfoBo;
-import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.customer.domain.PartnerContacts;
+import org.dromara.customer.domain.PartnerContract;
 import org.dromara.customer.domain.PartnerInfo;
 import org.dromara.customer.domain.PartnerUser;
+import org.dromara.customer.domain.bo.PartnerInfoBo;
+import org.dromara.customer.domain.vo.PartnerInfoIndexDataVo;
+import org.dromara.customer.domain.vo.PartnerInfoVo;
+import org.dromara.customer.domain.vo.PartnerManageIndexDataVo;
+import org.dromara.customer.mapper.PartnerContactsMapper;
+import org.dromara.customer.mapper.PartnerContractMapper;
 import org.dromara.customer.mapper.PartnerInfoMapper;
 import org.dromara.customer.mapper.PartnerUserMapper;
 import org.dromara.customer.service.IPartnerInfoService;
-import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.product.api.RemoteOrderInfoService;
+import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.dto.PartnerOrderIndexDto;
+import org.dromara.system.api.RemoteDictService;
+import org.dromara.system.api.domain.vo.RemoteDictDataVo;
+import org.springframework.stereotype.Service;
 
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 伙伴商基本信息Service业务层处理
@@ -38,6 +53,17 @@ public class PartnerInfoServiceImpl extends ServiceImpl<PartnerInfoMapper, Partn
 
     private final PartnerInfoMapper baseMapper;
     private final PartnerUserMapper partnerUserMapper;
+    private final PartnerContractMapper partnerContractMapper;
+    private final PartnerContactsMapper partnerContactsMapper;
+
+    @DubboReference
+    private RemoteDictService remoteDictService;
+
+    @DubboReference
+    private RemoteOrderInfoService remoteOrderInfoService;
+
+    @DubboReference
+    private RemoteProductService remoteProductService;
 
     /**
      * 查询伙伴商基本信息
@@ -209,7 +235,7 @@ public class PartnerInfoServiceImpl extends ServiceImpl<PartnerInfoMapper, Partn
     private String generatePartnerNo() {
         // 获取当前年份
         String year = String.valueOf(java.time.LocalDate.now().getYear());
-        
+
         // 查询当年最大的编号
         LambdaQueryWrapper<PartnerInfo> lqw = Wrappers.lambdaQuery();
         lqw.select(PartnerInfo::getPartnerNo);
@@ -231,8 +257,202 @@ public class PartnerInfoServiceImpl extends ServiceImpl<PartnerInfoMapper, Partn
                 log.warn("解析伙伴商编号失败: {}", maxRecord.getPartnerNo());
             }
         }
-        
+
         // 格式化为 P + 年份 + 3位序号,如 P2026001
         return String.format("P%s%03d", year, nextNum);
     }
+
+    @Override
+    public R<PartnerManageIndexDataVo> partnerManageIndexData() {
+        PartnerManageIndexDataVo vo = new PartnerManageIndexDataVo();
+        LocalDate today = LocalDate.now();
+
+        // 1. 伙伴商总数
+        vo.setPartnerTotal(baseMapper.selectCount(null));
+
+        // 2. 本月新增入驻
+        LocalDate firstDayOfMonth = today.withDayOfMonth(1);
+        vo.setMonthlyNew(baseMapper.selectCount(new LambdaQueryWrapper<PartnerInfo>()
+            .ge(PartnerInfo::getCreateTime, java.sql.Date.valueOf(firstDayOfMonth))
+            .lt(PartnerInfo::getCreateTime, java.sql.Date.valueOf(today.plusDays(1)))
+        ));
+
+        // 3. 季度新增入驻
+        int quarterStartMonth = ((today.getMonthValue() - 1) / 3) * 3 + 1;
+        LocalDate firstDayOfQuarter = LocalDate.of(today.getYear(), quarterStartMonth, 1);
+        vo.setQuarterlyNew(baseMapper.selectCount(new LambdaQueryWrapper<PartnerInfo>()
+            .ge(PartnerInfo::getCreateTime, java.sql.Date.valueOf(firstDayOfQuarter))
+            .lt(PartnerInfo::getCreateTime, java.sql.Date.valueOf(today.plusDays(1)))
+        ));
+
+        // 4. 合作中项目数(PartnerContract中cooperationId去重)
+        List<PartnerContract> contracts = partnerContractMapper.selectList(
+            new LambdaQueryWrapper<PartnerContract>()
+                .isNotNull(PartnerContract::getCooperationId)
+                .select(PartnerContract::getCooperationId)
+        );
+        vo.setCooperationProjectCount(contracts.stream()
+            .map(PartnerContract::getCooperationId)
+            .filter(Objects::nonNull)
+            .distinct()
+            .count());
+
+        // 5. 近半年新增伙伴商趋势
+        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("M月");
+        List<PartnerManageIndexDataVo.MonthTrend> monthlyTrend = new ArrayList<>();
+        for (int i = 5; i >= 0; i--) {
+            LocalDate monthStart = today.minusMonths(i).withDayOfMonth(1);
+            LocalDate monthEnd = monthStart.plusMonths(1);
+
+            PartnerManageIndexDataVo.MonthTrend trend = new PartnerManageIndexDataVo.MonthTrend();
+            trend.setMonth(monthStart.format(monthFormatter));
+            trend.setCount(baseMapper.selectCount(new LambdaQueryWrapper<PartnerInfo>()
+                .ge(PartnerInfo::getCreateTime, java.sql.Date.valueOf(monthStart))
+                .lt(PartnerInfo::getCreateTime, java.sql.Date.valueOf(monthEnd))
+            ));
+            monthlyTrend.add(trend);
+        }
+        vo.setMonthlyTrend(monthlyTrend);
+
+        // 6. 伙伴合作型态分布
+        List<PartnerInfo> allPartners = baseMapper.selectList(
+            new LambdaQueryWrapper<PartnerInfo>()
+                .isNotNull(PartnerInfo::getPartnerCooperateType)
+                .select(PartnerInfo::getPartnerCooperateType)
+        );
+        Map<Long, Long> typeCountMap = allPartners.stream()
+            .filter(p -> p.getPartnerCooperateType() != null)
+            .collect(Collectors.groupingBy(PartnerInfo::getPartnerCooperateType, Collectors.counting()));
+
+        // 查询字典获取类型名称
+        List<RemoteDictDataVo> cooperateTypeDicts = remoteDictService.selectDictDataByType("cooperate_type");
+        Map<String, String> dictMap = CollUtil.emptyIfNull(cooperateTypeDicts).stream()
+            .collect(Collectors.toMap(RemoteDictDataVo::getDictValue, RemoteDictDataVo::getDictLabel, (k1, k2) -> k1));
+
+        List<PartnerManageIndexDataVo.TypeDistribution> typeDistributions = typeCountMap.entrySet().stream()
+            .map(entry -> {
+                PartnerManageIndexDataVo.TypeDistribution td = new PartnerManageIndexDataVo.TypeDistribution();
+                String typeName = dictMap.get(String.valueOf(entry.getKey()));
+                td.setName(typeName != null ? typeName : "未知");
+                td.setValue(entry.getValue());
+                return td;
+            }).collect(Collectors.toList());
+        vo.setTypeDistribution(typeDistributions);
+
+        // 7. 最新入驻伙伴商列表(最新8条)
+        List<PartnerInfo> latestPartners = baseMapper.selectList(
+            new LambdaQueryWrapper<PartnerInfo>()
+                .orderByDesc(PartnerInfo::getCreateTime)
+                .last("LIMIT 8")
+        );
+
+        if (CollUtil.isNotEmpty(latestPartners)) {
+            Set<Long> partnerIds = latestPartners.stream()
+                .map(PartnerInfo::getId)
+                .collect(Collectors.toSet());
+
+            // 查询联系人,优先取contactType=1,没有则取contactType=2的任意一个
+            List<PartnerContacts> allContacts = partnerContactsMapper.selectList(
+                new LambdaQueryWrapper<PartnerContacts>()
+                    .in(PartnerContacts::getPartnerId, partnerIds)
+            );
+
+            Map<Long, PartnerContacts> contactMap = allContacts.stream()
+                .collect(Collectors.groupingBy(
+                    PartnerContacts::getPartnerId,
+                    Collectors.collectingAndThen(
+                        Collectors.toList(),
+                        list -> {
+                            // 先找type=1
+                            Optional<PartnerContacts> type1 = list.stream()
+                                .filter(c -> c.getContactType() != null && c.getContactType() == 1)
+                                .findFirst();
+                            if (type1.isPresent()) return type1.get();
+                            // 再找type=2
+                            Optional<PartnerContacts> type2 = list.stream()
+                                .filter(c -> c.getContactType() != null && c.getContactType() == 2)
+                                .findFirst();
+                            return type2.orElse(null);
+                        }
+                    )
+                ));
+
+            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            List<PartnerManageIndexDataVo.LatestPartner> partnerList = latestPartners.stream().map(p -> {
+                PartnerManageIndexDataVo.LatestPartner lp = new PartnerManageIndexDataVo.LatestPartner();
+                lp.setCompanyName(p.getPartnerName());
+                lp.setPartnerCooperateType(p.getPartnerCooperateType());
+
+                PartnerContacts contact = contactMap.get(p.getId());
+                if (contact != null) {
+                    lp.setContact(contact.getName());
+                    lp.setPhone(contact.getPhone());
+                }
+
+                if (p.getCreateTime() != null) {
+                    lp.setJoinTime(p.getCreateTime().toInstant()
+                        .atZone(ZoneId.systemDefault())
+                        .toLocalDateTime().format(dateTimeFormatter));
+                }
+                return lp;
+            }).collect(Collectors.toList());
+            vo.setLatestPartners(partnerList);
+        } else {
+            vo.setLatestPartners(Collections.emptyList());
+        }
+
+        return R.ok(vo);
+    }
+
+    @Override
+    public R<PartnerInfoIndexDataVo> partnerInfoIndexData(Long partnerId) {
+        PartnerInfoIndexDataVo vo = new PartnerInfoIndexDataVo();
+
+        // 1. 远程获取订单统计数据
+        PartnerOrderIndexDto orderData = remoteOrderInfoService.getPartnerOrderIndex(partnerId);
+        if (orderData != null) {
+            vo.setTodayOrders(orderData.getTodayOrders());
+            vo.setWeekRevenue(orderData.getWeekRevenue());
+            vo.setPendingShipment(orderData.getPendingShipment());
+
+            // 发货量走势
+            if (CollUtil.isNotEmpty(orderData.getShipmentTrend())) {
+                vo.setShipmentTrend(orderData.getShipmentTrend().stream().map(ds -> {
+                    PartnerInfoIndexDataVo.ShipmentTrend st = new PartnerInfoIndexDataVo.ShipmentTrend();
+                    st.setDate(ds.getDate());
+                    st.setCount(ds.getCount());
+                    return st;
+                }).collect(Collectors.toList()));
+            }
+
+            // 商品类型销售占比
+            if (CollUtil.isNotEmpty(orderData.getProductTypeSales())) {
+                vo.setProductTypeSales(orderData.getProductTypeSales().stream().map(ts -> {
+                    PartnerInfoIndexDataVo.ProductTypeSales pts = new PartnerInfoIndexDataVo.ProductTypeSales();
+                    pts.setName(ts.getName());
+                    pts.setValue(ts.getValue());
+                    return pts;
+                }).collect(Collectors.toList()));
+            }
+
+            // 最新发货动态
+            if (CollUtil.isNotEmpty(orderData.getLatestShipments())) {
+                vo.setLatestShipments(orderData.getLatestShipments().stream().map(so -> {
+                    PartnerInfoIndexDataVo.LatestShipment ls = new PartnerInfoIndexDataVo.LatestShipment();
+                    ls.setOrderNo(so.getOrderNo());
+                    ls.setProductName(so.getProductName());
+                    ls.setAmount(so.getAmount());
+                    ls.setCustomer(so.getCustomer());
+                    ls.setStatus(so.getStatus());
+                    ls.setDate(so.getDate());
+                    return ls;
+                }).collect(Collectors.toList()));
+            }
+        }
+
+        // 2. 在售商品数
+        vo.setOnSaleProducts(remoteProductService.getTotalProductCount());
+
+        return R.ok(vo);
+    }
 }

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContactServiceImpl.java

@@ -18,6 +18,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
 import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.customer.domain.CustomerContact;
 import org.dromara.customer.domain.SupplierContact;
 import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.bo.SupplierContactBo;
@@ -157,6 +158,8 @@ public class SupplierContactServiceImpl extends ServiceImpl<SupplierContactMappe
         lqw.eq(StringUtils.isNotBlank(bo.getPhone()), SupplierContact::getPhone, bo.getPhone());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), SupplierContact::getStatus, bo.getStatus());
         lqw.eq(StringUtils.isNotBlank(bo.getUserNo()), SupplierContact::getUserNo, bo.getUserNo());
+        lqw.between(ObjectUtil.isNotEmpty(params.get("beginTime")) && ObjectUtil.isNotEmpty(params.get("endTime")),
+            SupplierContact::getCreateTime, params.get("beginTime"), params.get("endTime"));
         return lqw;
     }
 

+ 63 - 36
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContractServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.customer.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -13,6 +14,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.customer.domain.SupplierContact;
 import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.dto.ContractCountDTO;
 import org.dromara.customer.domain.vo.SupplierContactVo;
@@ -73,46 +75,71 @@ public class SupplierContractServiceImpl  extends ServiceImpl<SupplierContractMa
      */
     @Override
     public TableDataInfo<SupplierContractVo> queryPageList(SupplierContractBo bo, PageQuery pageQuery) {
-        // 首先从SupplierInfo表进行分页查询
+        // 1. 先查询所有有合同的供应商ID(先过滤)
+        LambdaQueryWrapper<SupplierContract> contractWrapper = Wrappers.lambdaQuery();
+        contractWrapper.select(SupplierContract::getSupplierId)
+            .isNotNull(SupplierContract::getSupplierId)
+            .groupBy(SupplierContract::getSupplierId)
+            .having("COUNT(*) > 0");
+        List<SupplierContract> contractList = baseMapper.selectList(contractWrapper);
+            
+        // 提取有合同的供应商ID集合(防止contractList为null)
+        Set<Long> supplierIdsWithContracts = (contractList == null ? new ArrayList<SupplierContract>() : contractList).stream()
+            .map(SupplierContract::getSupplierId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+            
+        // 如果没有供应商有合同,直接返回空结果
+        if (supplierIdsWithContracts.isEmpty()) {
+            Page<SupplierContractVo> emptyResult = new Page<>();
+            emptyResult.setRecords(new ArrayList<>());
+            emptyResult.setTotal(0L);
+            emptyResult.setSize(pageQuery.getPageSize());
+            emptyResult.setCurrent(pageQuery.getPageNum());
+            return TableDataInfo.build(emptyResult);
+        }
+            
+        // 2. 根据有合同的供应商ID查询供应商信息(带分页)
         LambdaQueryWrapper<SupplierInfo> supplierInfoWrapper = Wrappers.lambdaQuery();
+        supplierInfoWrapper.in(SupplierInfo::getId, supplierIdsWithContracts);
+            
+        // 添加查询条件
         if (bo.getSupplierName() != null) {
             supplierInfoWrapper.eq(SupplierInfo::getEnterpriseName, bo.getSupplierName());
         }
-        if (bo.getSupplierId()!=null){
+        if (bo.getSupplierId() != null) {
             supplierInfoWrapper.eq(SupplierInfo::getId, bo.getSupplierId());
         }
-        if (bo.getSupplierNo()!=null){
+        if (bo.getSupplierNo() != null) {
             supplierInfoWrapper.eq(SupplierInfo::getSupplierNo, bo.getSupplierNo());
         }
-
-        // 添加其他SupplierInfo表的查询条件
+            
+        // 排序
         supplierInfoWrapper.orderByDesc(SupplierInfo::getSupplierNo);
-
-        // 执行分页查询供应商信息
+            
+        // 执行分页查询
         Page<SupplierInfo> supplierPage = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
         IPage<SupplierInfo> supplierInfoPage = supplierInfoService.page(supplierPage, supplierInfoWrapper);
         List<SupplierInfo> supplierInfoList = supplierInfoPage.getRecords();
-
-        // 获取所有供应商ID,用于后续查询合同统计信息
-        List<Long> supplierIds = supplierInfoList.stream()
+            
+        // 3. 查询这些供应商的合同统计信息(防止supplierInfoList为null)
+        List<Long> currentSupplierIds = (supplierInfoList == null ? new ArrayList<SupplierInfo>() : supplierInfoList).stream()
             .map(SupplierInfo::getId)
+            .filter(Objects::nonNull)
             .collect(Collectors.toList());
-
-
-
-        // 查询所有供应商的合同统计信息
+            
         Map<Long, ContractCountDTO> contractStatsMap = new HashMap<>();
-        if (!supplierIds.isEmpty()) {
-            // 查询所有相关合同
-            LambdaQueryWrapper<SupplierContract> contractWrapper = Wrappers.lambdaQuery();
-            contractWrapper.in(SupplierContract::getSupplierId, supplierIds);
-            List<SupplierContract> allContracts = baseMapper.selectList(contractWrapper);
-
-            // 获取当前时间(用于判断合同是否过期)
+        if (!currentSupplierIds.isEmpty()) {
+            // 查询当前页供应商的所有合同
+            LambdaQueryWrapper<SupplierContract> pageContractWrapper = Wrappers.lambdaQuery();
+            pageContractWrapper.in(SupplierContract::getSupplierId, currentSupplierIds);
+            List<SupplierContract> pageContracts = baseMapper.selectList(pageContractWrapper);
+                
+            // 获取当前时间(用于判断合同是否过期)
             Date now = new Date();
-
+                
             // 按供应商ID分组统计合同信息
-            contractStatsMap = allContracts.stream()
+            contractStatsMap = pageContracts.stream()
                 .collect(Collectors.groupingBy(
                     SupplierContract::getSupplierId,
                     Collectors.collectingAndThen(
@@ -120,43 +147,43 @@ public class SupplierContractServiceImpl  extends ServiceImpl<SupplierContractMa
                         list -> {
                             // 统计总数
                             long total = list.size();
-                            // 统计有效期内合同数(状态为已生效 且 到期时间晚于当前时间)
+                            // 统计有效期内合同数(状态为已生效 且 到期时间晚于当前时间)
                             long validCount = list.stream()
                                 .filter(contract ->
                                     2L != (contract.getContractStatus())
                                         && contract.getContractEndTime() != null && contract.getContractEndTime().after(now)
                                 ).count();
-                            // 统计失效合同数(总数 - 有效数)
+                            // 统计失效合同数(总数 - 有效数)
                             long invalidCount = total - validCount;
                             return new ContractCountDTO(total, validCount, invalidCount);
                         }
                     )
                 ));
         }
-
-        // 将供应商信息和合同统计信息组合成VO列表
-        final Map<Long, ContractCountDTO> finalContractStatsMap = contractStatsMap; // 创建final副本
-        List<SupplierContractVo> contractStats = supplierInfoList.stream()
+            
+        // 4. 将供应商信息和合同统计信息组合成VO列表(防止supplierInfoList为null)
+        final Map<Long, ContractCountDTO> finalContractStatsMap = contractStatsMap;
+        List<SupplierContractVo> contractStats = (supplierInfoList == null ? new ArrayList<SupplierInfo>() : supplierInfoList).stream()
             .map(supplierInfo -> {
                 SupplierContractVo vo = new SupplierContractVo();
                 vo.setSupplierId(supplierInfo.getId());
                 vo.setSupplierNo(supplierInfo.getSupplierNo());
                 vo.setSupplierName(supplierInfo.getEnterpriseName());
-
-                // 获取合同统计信息,如果没有则创建默认值为0的统计对象
-                ContractCountDTO defaultCountDTO = new ContractCountDTO(0, 0, 0);
+                    
+                // 获取合同统计信息
                 ContractCountDTO countDTO = finalContractStatsMap.getOrDefault(supplierInfo.getId(),
-                    defaultCountDTO);
-
+                    new ContractCountDTO(0, 0, 0));
+                    
                 // 设置合同数统计
                 vo.setContractNum(String.valueOf(countDTO.getTotal()));
                 vo.setValidContract(String.valueOf(countDTO.getValidCount()));
                 vo.setInvalidContract(String.valueOf(countDTO.getInvalidCount()));
-
+                    
                 return vo;
             })
             .collect(Collectors.toList());
-        // 构建分页结果
+            
+        // 5. 构建分页结果
         Page<SupplierContractVo> result = new Page<>();
         result.setRecords(contractStats);
         result.setTotal(supplierInfoPage.getTotal());

+ 246 - 14
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoServiceImpl.java

@@ -1,6 +1,7 @@
 package org.dromara.customer.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.crypto.digest.BCrypt;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -38,11 +39,9 @@ import org.dromara.customer.utils.qcc.domain.CompanyInfoResponse;
 import org.dromara.product.api.RemoteCategoryService;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.RemoteProductBrand;
-import org.dromara.system.api.RemoteComStaffService;
-import org.dromara.system.api.RemoteSupplierTypeService;
-import org.dromara.system.api.RemoteUserService;
+import org.dromara.system.api.*;
 import org.dromara.system.api.domain.bo.RemoteUserBo;
-import org.dromara.system.api.domain.vo.RemoteSupplierTypeVo;
+import org.dromara.system.api.domain.vo.*;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -103,6 +102,21 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
     @DubboReference
     private final RemoteSupplierTypeService remoteSupplierTypeService;
 
+    @DubboReference
+    private RemoteComCompanyService remoteComCompanyService;
+
+    @DubboReference
+    private RemoteErpStaffService remoteErpStaffService;
+
+    @DubboReference
+    private RemoteComCurrencyService remoteComCurrencyService;
+
+    @DubboReference
+    private RemoteProductTaxrateService remoteProductTaxrateService;
+
+    @DubboReference
+    private RemoteSupplierLevelService remoteSupplierLevelService;
+
 
     /**
      * 新增供应商信息
@@ -206,11 +220,11 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
             //状态为修改待审核
             supplierInfoVo.setSupplyStatus(SupplierStatusEnum.REVIEW_UPDATED.getCode());
             //先copy到临时表
-            SupplierInfoTemporary supplierInfoTemporary =  supplierInfoTemporaryService.getOne(Wrappers.lambdaQuery(SupplierInfoTemporary.class)
+            SupplierInfoTemporary supplierInfoTemporary = supplierInfoTemporaryService.getOne(Wrappers.lambdaQuery(SupplierInfoTemporary.class)
                 .eq(SupplierInfoTemporary::getSupplierId, bo.getId())
                 .last("limit 1")
             );
-            if(supplierInfoTemporary == null){
+            if (supplierInfoTemporary == null) {
                 supplierInfoTemporary = new SupplierInfoTemporary();
             }
             BeanUtils.copyProperties(bo, supplierInfoTemporary, "id");
@@ -370,17 +384,25 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
                 throw new RuntimeException("更新供应商待审核基础数据失败,请联系管理员", e);
             }
         }
-        SupplierInfoTemporary supplierInfoTemporary =  supplierInfoTemporaryService.getOne(Wrappers.lambdaQuery(SupplierInfoTemporary.class)
+        SupplierInfoTemporary supplierInfoTemporary = supplierInfoTemporaryService.getOne(Wrappers.lambdaQuery(SupplierInfoTemporary.class)
             .eq(SupplierInfoTemporary::getSupplierId, bo.getId())
             .last("limit 1")
         );
-        if(supplierInfoTemporary == null){
+        if (supplierInfoTemporary == null) {
             supplierInfoTemporary = new SupplierInfoTemporary();
             BeanUtils.copyProperties(bo, supplierInfoTemporary, "id");
             supplierInfoTemporary.setSupplyStatus(bo.getSupplyStatus());
             supplierInfoTemporaryService.saveOrUpdate(supplierInfoTemporary);
-        }else{
-            if(bo.getSupplyStatus() == SupplierStatusEnum.OFFICIAL_SUPPLIER.getCode()){
+        } else {
+            if (bo.getSupplyStatus() == SupplierStatusEnum.OFFICIAL_SUPPLIER.getCode()) {
+                supplierInfoTemporary.setSupplyStatus(bo.getSupplyStatus());
+                supplierInfoTemporaryService.saveOrUpdate(supplierInfoTemporary);
+                SupplierInfo supplierInfo = BeanUtil.toBean(supplierInfoTemporary, SupplierInfo.class);
+                supplierInfo.setId(supplierInfoTemporary.getSupplierId());
+                return baseMapper.updateById(supplierInfo) > 0;
+            }
+
+            if (bo.getSupplyStatus() == SupplierStatusEnum.REVIEW_FAILED.getCode()) {
                 supplierInfoTemporary.setSupplyStatus(bo.getSupplyStatus());
                 supplierInfoTemporaryService.saveOrUpdate(supplierInfoTemporary);
                 SupplierInfo supplierInfo = BeanUtil.toBean(supplierInfoTemporary, SupplierInfo.class);
@@ -639,13 +661,13 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
             .eq(SupplierInfo::getId, id));
         SupplierInfoVo supplierInfoVo = new SupplierInfoVo();
 //        if (supplierInfoVo1 != null && supplierInfoVo1.getSupplyStatus() == SupplierStatusEnum.REVIEW_UPDATED.getCode()) {
-        if (supplierInfoVo1 != null ) {
+        if (supplierInfoVo1 != null) {
             SupplierInfoTemporaryVo supplierInfoTemporaryVo = supplierInfoTemporaryService.getVoOne(id);
             if (supplierInfoTemporaryVo != null) {
                 BeanUtils.copyProperties(supplierInfoTemporaryVo, supplierInfoVo);
             }
         } else {
-                supplierInfoVo = baseMapper.selectVoById(id);
+            supplierInfoVo = baseMapper.selectVoById(id);
         }
         SupplierInfoVo supplierInformationVo = handleProcurementInfo(supplierInfoVo);
         //返回工商信息
@@ -802,7 +824,7 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
                 vo.setSupplierNo(supplierInfo.getSupplierNo());
 //                vo.setSupplyStatus(supplierInfo.getSupplyStatus());
                 return vo;
-            }).collect(Collectors.toList());
+            }).filter(Objects::nonNull).collect(Collectors.toList());
 
             // 批量处理扩展信息
             supplierVos = batchHandleBaseExtInfo(supplierVos);
@@ -2131,7 +2153,7 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
             add.setSupplierId(supplierInfo.getId());
             add.setSupplyStatus(0L);
             supplierInfoTemporaryService.updateById(add);
-        }else {
+        } else {
             SupplierInfoTemporary add = BeanUtil.toBean(supplierInfo, SupplierInfoTemporary.class);
             add.setSupplierId(supplierInfo.getId());
             add.setSupplyStatus(0L);
@@ -2518,4 +2540,214 @@ public class SupplierInfoServiceImpl extends ServiceImpl<SupplierInfoMapper, Sup
 
         return temporary;
     }
+
+    /**
+     * 导出模板数据:查询指定数量的供应商数据,转换为导入模板格式
+     */
+    @Override
+    public List<SupplierInfoImportVo> queryImportTemplateList(int limit) {
+        // 1. 查询供应商主表数据
+        List<SupplierInfoVo> list;
+        if (limit <= 0) {
+            // 导出全部
+            list = baseMapper.selectVoList(new LambdaQueryWrapper<>());
+        } else {
+            PageQuery pageQuery = new PageQuery();
+            pageQuery.setPageNum(1);
+            pageQuery.setPageSize(limit);
+            TableDataInfo<SupplierInfoVo> pageResult = queryPageList(new SupplierInfoBo(), pageQuery);
+            list = pageResult.getRows();
+        }
+
+        if (CollUtil.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+
+        // 2. 收集所有供应商ID
+        Set<Long> supplierIds = list.stream()
+            .map(SupplierInfoVo::getId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+
+        // 3. 查询供应商的ERP信息
+        Map<Long, SupplierErpInfoVo> erpInfoMap = new HashMap<>();
+        if (!supplierIds.isEmpty()) {
+            List<SupplierErpInfoVo> erpInfoList = supplierErpInfoMapper.selectVoList(
+                new LambdaQueryWrapper<SupplierErpInfo>().in(SupplierErpInfo::getSupplierId, supplierIds));
+            for (SupplierErpInfoVo vo : erpInfoList) {
+                erpInfoMap.put(vo.getSupplierId(), vo);
+            }
+        }
+
+        // 4. 收集需要远程查询的ID
+        Set<Long> companyIds = new HashSet<>();
+        Set<Long> supplierTypeIds = new HashSet<>();
+        Set<Long> erpStaffIds = new HashSet<>();
+        Set<Long> dealCurrencyIds = new HashSet<>();
+        Set<Long> rateIds = new HashSet<>();
+
+        for (SupplierInfoVo vo : list) {
+            if (vo.getOwnedCompany() != null) companyIds.add(vo.getOwnedCompany());
+            if (vo.getSupplierType() != null) supplierTypeIds.add(vo.getSupplierType());
+            SupplierErpInfoVo erpVo = erpInfoMap.get(vo.getId());
+            if (erpVo != null) {
+                if (erpVo.getPurchaseId() != null) erpStaffIds.add(erpVo.getPurchaseId());
+                if (erpVo.getDealCurrencyId() != null) dealCurrencyIds.add(erpVo.getDealCurrencyId());
+                if (erpVo.getRateId() != null) rateIds.add(erpVo.getRateId());
+            }
+        }
+
+        // 5. 批量查询远程服务
+        // 公司
+        Map<Long, RemoteComCompanyVo> companyMap = new HashMap<>();
+        if (!companyIds.isEmpty()) {
+            List<RemoteComCompanyVo> companyList = remoteComCompanyService.selectCompanyList();
+            for (RemoteComCompanyVo vo : companyList) {
+                if (companyIds.contains(vo.getId())) {
+                    companyMap.put(vo.getId(), vo);
+                }
+            }
+        }
+
+        // 供应商类型(按ID逐个查询,避免 queryList 的 dataSource 过滤导致遗漏)
+        Map<Long, RemoteSupplierTypeVo> supplierTypeMap = new HashMap<>();
+        for (Long id : supplierTypeIds) {
+            RemoteSupplierTypeVo typeVo = remoteSupplierTypeService.selectByTypeId(id);
+            if (typeVo != null) {
+                supplierTypeMap.put(id, typeVo);
+            }
+        }
+
+        // 采购员(ERP人员)
+        Map<Long, String> erpStaffNameMap = erpStaffIds.isEmpty()
+            ? Collections.emptyMap()
+            : remoteErpStaffService.selectStaffNameByIds(erpStaffIds);
+
+        // 交易币别
+        Map<Long, RemoteComCurrencyVo> currencyMap = new HashMap<>();
+        if (!dealCurrencyIds.isEmpty()) {
+            List<RemoteComCurrencyVo> currencyList = remoteComCurrencyService.selectCurrencyByIds(dealCurrencyIds);
+            for (RemoteComCurrencyVo vo : currencyList) {
+                currencyMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 税码
+        Map<Long, RemoteProductTaxrateVo> taxrateMap = new HashMap<>();
+        if (!rateIds.isEmpty()) {
+            List<RemoteProductTaxrateVo> taxrateList = remoteProductTaxrateService.selectTaxrateByIds(rateIds);
+            for (RemoteProductTaxrateVo vo : taxrateList) {
+                taxrateMap.put(vo.getId(), vo);
+            }
+        }
+
+        // 供应商等级(按ID逐个查询,每次导出最多30条)
+        Map<Long, RemoteSupplierLevelVo> supplierLevelMap = new HashMap<>();
+        Set<Long> levelIds = list.stream()
+            .map(SupplierInfoVo::getCooperateLevel)
+            .filter(Objects::nonNull)
+            .map(s -> {
+                try {
+                    return Long.valueOf(s);
+                } catch (NumberFormatException e) {
+                    return null;
+                }
+            })
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+        for (Long levelId : levelIds) {
+            RemoteSupplierLevelVo levelVo = remoteSupplierLevelService.selectByLevelId(levelId);
+            if (levelVo != null) {
+                supplierLevelMap.put(levelId, levelVo);
+            }
+        }
+
+        // ERP人员编码(通过姓名反查staffCode)
+        Map<String, String> staffNameToCodeMap = new HashMap<>();
+        for (String staffName : new HashSet<>(erpStaffNameMap.values())) {
+            if (StringUtils.isNotBlank(staffName)) {
+                RemoteErpStaffVo staffVo = remoteErpStaffService.selectStaffByStaffNameOne(staffName);
+                if (staffVo != null && StringUtils.isNotBlank(staffVo.getStaffCode())) {
+                    staffNameToCodeMap.put(staffName, staffVo.getStaffCode());
+                }
+            }
+        }
+
+        // 6. 构建导出VO列表
+        List<SupplierInfoImportVo> exportList = new ArrayList<>();
+        for (SupplierInfoVo vo : list) {
+            SupplierInfoImportVo importVo = new SupplierInfoImportVo();
+
+            // 公司
+            RemoteComCompanyVo companyVo = companyMap.get(vo.getOwnedCompany());
+            importVo.setCompanyCode(companyVo != null ? companyVo.getCompanyCode() : null);
+            importVo.setOwnedCompanyName(companyVo != null ? companyVo.getCompanyName() : null);
+
+            // 基本信息
+            importVo.setSupplierNo(vo.getSupplierNo());
+            importVo.setEnterpriseName(vo.getEnterpriseName());
+            importVo.setBusinessName(vo.getBusinessName());
+            importVo.setShortName(vo.getShortName());
+            importVo.setSocialCreditCode(vo.getSocialCreditCode());
+
+            // 供应商类型
+            RemoteSupplierTypeVo typeVo = supplierTypeMap.get(vo.getSupplierType());
+            importVo.setSupplierTypeNo(typeVo != null ? typeVo.getSupplierTypeNo() : null);
+            importVo.setSupplierTypeName(typeVo != null ? typeVo.getSupplierTypeName() : null);
+
+            // 供应商等级
+            Long levelId = null;
+            if (vo.getCooperateLevel() != null) {
+                try {
+                    levelId = Long.valueOf(vo.getCooperateLevel());
+                } catch (NumberFormatException ignored) {
+                }
+            }
+            RemoteSupplierLevelVo levelVo = levelId != null ? supplierLevelMap.get(levelId) : null;
+            importVo.setSupplierLevelNo(levelVo != null ? levelVo.getSupplierLevelNo() : null);
+            importVo.setSupplierLevelName(levelVo != null ? levelVo.getSupplierLevelName() : null);
+
+            // 联系信息
+            importVo.setFixedPhone(vo.getFixedPhone());
+            importVo.setOfficeProvince(vo.getOfficeProvince());
+            importVo.setOfficeCity(vo.getOfficeCity());
+            importVo.setOfficeCounty(vo.getOfficeCounty());
+            importVo.setOfficeAddress(vo.getOfficeAddress());
+
+            // ERP信息
+            SupplierErpInfoVo erpVo = erpInfoMap.get(vo.getId());
+            if (erpVo != null) {
+                // 采购员
+                String buyerName = erpStaffNameMap.get(erpVo.getPurchaseId());
+                importVo.setBuyerNo(staffNameToCodeMap.get(buyerName));
+                importVo.setBuyerName(buyerName);
+                importVo.setBuyerOne("");
+
+                // 付款类型
+                importVo.setBuyType(erpVo.getSettlementMethod());
+
+                // 开票类型
+                importVo.setInvoiceTypeNo(erpVo.getPurchaseInvoiceNo());
+                importVo.setInvoiceType(erpVo.getPurchaseInvoice());
+
+                // 单价含税
+                importVo.setUnitPrice(erpVo.getUnitPrice());
+
+                // 交易币别
+                RemoteComCurrencyVo currencyVo = currencyMap.get(erpVo.getDealCurrencyId());
+                importVo.setDealCurrency(currencyVo != null ? currencyVo.getCurrencyCode() : null);
+
+                // 税码
+                RemoteProductTaxrateVo taxrateVo = taxrateMap.get(erpVo.getRateId());
+                importVo.setRateName(taxrateVo != null ? taxrateVo.getTaxrateNo() : null);
+
+                // 账款归属
+                importVo.setAccountBelong(erpVo.getAccountBelong());
+            }
+
+            exportList.add(importVo);
+        }
+
+        return exportList;
+    }
 }

+ 28 - 8
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoTemporaryServiceImpl.java

@@ -1,6 +1,8 @@
 package org.dromara.customer.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
@@ -11,8 +13,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.customer.domain.SupplierBusinessInfo;
 import org.dromara.customer.domain.SupplierInfo;
+import org.dromara.customer.domain.vo.SupplierBusinessInfoVo;
 import org.dromara.customer.domain.vo.SupplierInfoVo;
+import org.dromara.customer.mapper.SupplierBusinessInfoMapper;
 import org.dromara.customer.mapper.SupplierInfoMapper;
 import org.springframework.stereotype.Service;
 import org.dromara.customer.domain.bo.SupplierInfoTemporaryBo;
@@ -41,6 +46,8 @@ public class SupplierInfoTemporaryServiceImpl  extends ServiceImpl<SupplierInfoT
 
     private final SupplierInfoMapper supplierInfoMapper;
 
+    private final SupplierBusinessInfoMapper supplierBusinessInfoMapper;
+
     /**
      * 查询供应商临时信息
      *
@@ -172,6 +179,14 @@ public class SupplierInfoTemporaryServiceImpl  extends ServiceImpl<SupplierInfoT
             new LambdaQueryWrapper<SupplierInfoTemporary>()
             .eq(SupplierInfoTemporary::getSupplierId, bo.getId())
         );
+        //获取供应商编号的最大值
+        SupplierInfoVo supplierInfoVo = supplierInfoMapper.selectVoOne(new LambdaQueryWrapper<SupplierInfo>()
+            .select(SupplierInfo::getSupplierNo)
+            .last("limit 1")
+            .orderByDesc(SupplierInfo::getSupplierNo)
+        );
+        long l = Long.parseLong(supplierInfoVo.getSupplierNo()) + 1;
+        String supplierNo = String.valueOf(l);
         if (supplierInfoTemporary != null) {
             add.setId(supplierInfoTemporary.getId());
             add.setSupplierId(bo.getId());
@@ -184,20 +199,25 @@ public class SupplierInfoTemporaryServiceImpl  extends ServiceImpl<SupplierInfoT
                     add.setSupplierId(supplierInfo.getId());
                 }
             }else{
-                //获取供应商编号的最大值
-                SupplierInfoVo supplierInfoVo = supplierInfoMapper.selectVoOne(new LambdaQueryWrapper<SupplierInfo>()
-                    .select(SupplierInfo::getSupplierNo)
-                    .last("limit 1")
-                    .orderByDesc(SupplierInfo::getSupplierNo)
-                );
-                long l = Long.parseLong(supplierInfoVo.getSupplierNo()) + 1;
-                String supplierNo = String.valueOf(l);
+
                 SupplierInfo supplierInfo = BeanUtil.toBean(add, SupplierInfo.class);
                 supplierInfo.setSupplierNo(supplierNo);
                 supplierInfoMapper.insert(supplierInfo);
                 add.setSupplierId(supplierInfo.getId());
+
+                SupplierBusinessInfoVo supplierBusinessInfoVo = supplierBusinessInfoMapper.selectVoOne(new LambdaQueryWrapper<SupplierBusinessInfo>()
+                    .eq(SupplierBusinessInfo::getSupplierId, bo.getId()))
+                    ;
+                //保存工商信息
+                if (ObjectUtil.isEmpty(supplierBusinessInfoVo)) {
+                    String otherCustomers = bo.getOtherCustomers();
+                    SupplierBusinessInfo businessInfo = JSONUtil.toBean(otherCustomers, SupplierBusinessInfo.class);
+                    businessInfo.setSupplierId(supplierInfo.getId());
+                    supplierBusinessInfoMapper.insert(businessInfo);
+                }
             }
             add.setId(null);
+            add.setSupplierNo(supplierNo);
             add.setSupplyStatus(bo.getSupplyStatus());
             boolean flag = baseMapper.insert(add) > 0;
             if (flag) {

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/utils/qcc/domain/Area.java

@@ -1,9 +1,12 @@
 package org.dromara.customer.utils.qcc.domain;
 
+import org.apache.ibatis.type.Alias;
+
 /**
  * 地区信息实体
  * 描述企业的地理位置信息
  */
+@Alias("QccArea")
 public class Area {
 
     /**

+ 7 - 0
ruoyi-modules/ruoyi-customer/src/main/resources/mapper/customer/TeamMemberMapper.xml

@@ -31,6 +31,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LIMIT 1
     </select>
 
+    <select id="selectByObjectNoAndRoleCodeWithDeleted" resultType="org.dromara.customer.domain.vo.TeamMemberVo">
+        SELECT * FROM team_member
+        WHERE object_no = #{objectNo} AND role_code = #{roleCode}
+        ORDER BY is_delete ASC, update_time DESC
+        LIMIT 1
+    </select>
+
     <update id="restoreMemberById">
         UPDATE team_member SET 
             is_delete = 0,

+ 230 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/erp/ErpPullController.java

@@ -7,6 +7,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
 import org.dromara.customer.api.RemoteErpCustomerService;
 import org.dromara.external.api.erp.domain.*;
 import org.dromara.product.api.RemoteErpProductService;
@@ -43,7 +45,11 @@ public class ErpPullController {
     private RemoteErpSystemService remoteErpSystemService;
 
     @PostMapping()
+    @Log(title = "ero数据拉取", businessType = BusinessType.OTHER)
     public R<Void> erp(@RequestParam String type, @RequestBody Map<String,Object> map){
+        log.info("ERP数据拉取: " + type);
+        log.info("ERP数据拉取参数: " + map);
+        //公司
         if("syncCompany".equals(type)){
             ErpCompany bean = BeanUtil.toBean(map, ErpCompany.class);
             this.syncCompany(bean);
@@ -52,6 +58,230 @@ public class ErpPullController {
             ErpCompany bean = BeanUtil.toBean(map, ErpCompany.class);
             this.deleteCompany(bean);
         }
+        //商品分类
+        if("syncProductCategory".equals(type)){
+            ErpProductCategory bean = BeanUtil.toBean(map, ErpProductCategory.class);
+            this.syncProductCategory(bean);
+        }
+        if("deleteProductCategory".equals(type)){
+            ErpProductCategory bean = BeanUtil.toBean(map, ErpProductCategory.class);
+            this.deleteProductCategory(bean);
+        }
+        //人员
+        if("syncPerson".equals(type)){
+            ErpPerson bean = BeanUtil.toBean(map, ErpPerson.class);
+            this.syncPerson(bean);
+        }
+        if("deletePerson".equals(type)){
+            ErpPerson bean = BeanUtil.toBean(map, ErpPerson.class);
+            this.deletePerson(bean);
+        }
+        //仓库
+        if("syncWarehouse".equals(type)){
+            ErpWarehouse bean = BeanUtil.toBean(map, ErpWarehouse.class);
+            this.syncWarehouse(bean);
+        }
+        if("deleteWarehouse".equals(type)){
+            ErpWarehouse bean = BeanUtil.toBean(map, ErpWarehouse.class);
+            this.deleteWarehouse(bean);
+        }
+        //企业规模
+        if("syncCompanyScale".equals(type)){
+            ErpCompanyScale bean = BeanUtil.toBean(map, ErpCompanyScale.class);
+            this.syncCompanyScale(bean);
+        }
+        if("deleteCompanyScale".equals(type)){
+            ErpCompanyScale bean = BeanUtil.toBean(map, ErpCompanyScale.class);
+            this.deleteCompanyScale(bean);
+        }
+        //供应商类别
+        if("syncSupplierType".equals(type)){
+            ErpSupplierType bean = BeanUtil.toBean(map, ErpSupplierType.class);
+            this.syncSupplierType(bean);
+        }
+        if("deleteSupplierType".equals(type)){
+            ErpSupplierType bean = BeanUtil.toBean(map, ErpSupplierType.class);
+            this.deleteSupplierType(bean);
+        }
+        //出库配送信息
+        if("syncSalesDelivery".equals(type)){
+            ErpSalesDelivery bean = BeanUtil.toBean(map, ErpSalesDelivery.class);
+            this.syncSalesDelivery(bean);
+        }
+        //区县主数据
+        if("syncDistrict".equals(type)){
+            ErpDistrict bean = BeanUtil.toBean(map, ErpDistrict.class);
+            this.syncDistrict(bean);
+        }
+        if("deleteDistrict".equals(type)){
+            ErpDistrict bean = BeanUtil.toBean(map, ErpDistrict.class);
+            this.deleteDistrict(bean);
+        }
+        //品牌资料
+        if("syncBrand".equals(type)){
+            ErpBrand bean = BeanUtil.toBean(map, ErpBrand.class);
+            this.syncBrand(bean);
+        }
+        if("deleteBrand".equals(type)){
+            ErpBrand bean = BeanUtil.toBean(map, ErpBrand.class);
+            this.deleteBrand(bean);
+        }
+        //国家地区
+        if("syncCountry".equals(type)){
+            ErpCountry bean = BeanUtil.toBean(map, ErpCountry.class);
+            this.syncCountry(bean);
+        }
+        if("deleteCountry".equals(type)){
+            ErpCountry bean = BeanUtil.toBean(map, ErpCountry.class);
+            this.deleteCountry(bean);
+        }
+        //城市设定
+        if("syncCity".equals(type)){
+            ErpCity bean = BeanUtil.toBean(map, ErpCity.class);
+            this.syncCity(bean);
+        }
+        if("deleteCity".equals(type)){
+            ErpCity bean = BeanUtil.toBean(map, ErpCity.class);
+            this.deleteCity(bean);
+        }
+        //客户等级
+        if("syncCustomerGrade".equals(type)){
+            ErpCustomerGrade bean = BeanUtil.toBean(map, ErpCustomerGrade.class);
+            this.syncCustomerGrade(bean);
+        }
+        if("deleteCustomerGrade".equals(type)){
+            ErpCustomerGrade bean = BeanUtil.toBean(map, ErpCustomerGrade.class);
+            this.deleteCustomerGrade(bean);
+        }
+        //客户类别
+        if("syncCustomerType".equals(type)){
+            ErpCustomerType bean = BeanUtil.toBean(map, ErpCustomerType.class);
+            this.syncCustomerType(bean);
+        }
+        if("deleteCustomerType".equals(type)){
+            ErpCustomerType bean = BeanUtil.toBean(map, ErpCustomerType.class);
+            this.deleteCustomerType(bean);
+        }
+        //客户资料
+        if("syncCustomer".equals(type)){
+            ErpCustomer bean = BeanUtil.toBean(map, ErpCustomer.class);
+            this.syncCustomer(bean);
+        }
+        //岗位设定
+        if("syncPosition".equals(type)){
+            ErpPosition bean = BeanUtil.toBean(map, ErpPosition.class);
+            this.syncPosition(bean);
+        }
+        if("deletePosition".equals(type)){
+            ErpPosition bean = BeanUtil.toBean(map, ErpPosition.class);
+            this.deletePosition(bean);
+        }
+        //快递主数据
+        if("syncExpress".equals(type)){
+            ErpExpress bean = BeanUtil.toBean(map, ErpExpress.class);
+            this.syncExpress(bean);
+        }
+        if("deleteExpress".equals(type)){
+            ErpExpress bean = BeanUtil.toBean(map, ErpExpress.class);
+            this.deleteExpress(bean);
+        }
+        //收入费用设定
+        if("syncIncomeExpenseType".equals(type)){
+            ErpIncomeExpenseType bean = BeanUtil.toBean(map, ErpIncomeExpenseType.class);
+            this.syncIncomeExpenseType(bean);
+        }
+        if("deleteIncomeExpenseType".equals(type)){
+            ErpIncomeExpenseType bean = BeanUtil.toBean(map, ErpIncomeExpenseType.class);
+            this.deleteIncomeExpenseType(bean);
+        }
+        //收入转确认
+        if("confirmIncome".equals(type)){
+            ErpIncomeApplication bean = BeanUtil.toBean(map, ErpIncomeApplication.class);
+            this.confirmIncome(bean);
+        }
+        //省份设定
+        if("syncProvince".equals(type)){
+            ErpProvince bean = BeanUtil.toBean(map, ErpProvince.class);
+            this.syncProvince(bean);
+        }
+        if("deleteProvince".equals(type)){
+            ErpProvince bean = BeanUtil.toBean(map, ErpProvince.class);
+            this.deleteProvince(bean);
+        }
+        //税码设定
+        if("syncTaxCode".equals(type)){
+            ErpTaxCode bean = BeanUtil.toBean(map, ErpTaxCode.class);
+            this.syncTaxCode(bean);
+        }
+        if("deleteTaxCode".equals(type)){
+            ErpTaxCode bean = BeanUtil.toBean(map, ErpTaxCode.class);
+            this.deleteTaxCode(bean);
+        }
+        //行业别
+        if("syncIndustry".equals(type)){
+            ErpIndustry bean = BeanUtil.toBean(map, ErpIndustry.class);
+            this.syncIndustry(bean);
+        }
+        if("deleteIndustry".equals(type)){
+            ErpIndustry bean = BeanUtil.toBean(map, ErpIndustry.class);
+            this.deleteIndustry(bean);
+        }
+        //计量单位设定
+        if("syncUnit".equals(type)){
+            ErpUnit bean = BeanUtil.toBean(map, ErpUnit.class);
+            this.syncUnit(bean);
+        }
+        if("deleteUnit".equals(type)){
+            ErpUnit bean = BeanUtil.toBean(map, ErpUnit.class);
+            this.deleteUnit(bean);
+        }
+        //订单出库状态变更
+        if("updateSalesOrderStatus".equals(type)){
+            ErpSalesOrder bean = BeanUtil.toBean(map, ErpSalesOrder.class);
+            this.updateSalesOrderStatus(bean);
+        }
+        //费用转确认
+        if("confirmExpense".equals(type)){
+            ErpExpense bean = BeanUtil.toBean(map, ErpExpense.class);
+            this.confirmExpense(bean);
+        }
+        //部门设定
+        if("syncDepartment".equals(type)){
+            ErpDepartment bean = BeanUtil.toBean(map, ErpDepartment.class);
+            this.syncDepartment(bean);
+        }
+        if("deleteDepartment".equals(type)){
+            ErpDepartment bean = BeanUtil.toBean(map, ErpDepartment.class);
+            this.deleteDepartment(bean);
+        }
+        //银行设定
+        if("syncBank".equals(type)){
+            ErpBank bean = BeanUtil.toBean(map, ErpBank.class);
+            this.syncBank(bean);
+        }
+        if("deleteBank".equals(type)){
+            ErpBank bean = BeanUtil.toBean(map, ErpBank.class);
+            this.deleteBank(bean);
+        }
+        //销售价格清单
+        if("syncSalesPriceList".equals(type)){
+            ErpSalesPriceList bean = BeanUtil.toBean(map, ErpSalesPriceList.class);
+            this.syncSalesPriceList(bean);
+        }
+        if("syncCustomerSalesPriceList".equals(type)){
+            ErpCustomerSalesPriceList bean = BeanUtil.toBean(map, ErpCustomerSalesPriceList.class);
+            this.syncCustomerSalesPriceList(bean);
+        }
+        if("deleteSalesPriceList".equals(type)){
+            ErpSalesPriceList bean = BeanUtil.toBean(map, ErpSalesPriceList.class);
+            this.deleteSalesPriceList(bean);
+        }
+        //销售退货入库
+        if("syncSalesReturnApplication".equals(type)){
+            ErpSalesReturnApplication bean = BeanUtil.toBean(map, ErpSalesReturnApplication.class);
+            this.syncSalesReturnApplication(bean);
+        }
+
         return R.ok();
     }
 

+ 18 - 4
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyCommonController.java

@@ -1,16 +1,17 @@
 package org.dromara.external.controller.thirdparty;
 
+import cn.hutool.core.bean.BeanUtil;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.domain.R;
 import org.dromara.external.api.thirdparty.domain.bo.ThirdpartyProductBrandBo;
 import org.dromara.external.api.thirdparty.domain.bo.ThirdpartyProductUnitBo;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyAreaDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductBrandDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductCateDto;
-import org.dromara.external.api.thirdparty.domain.dto.ThirdpartyProductUnitDto;
+import org.dromara.external.api.thirdparty.domain.dto.*;
+import org.dromara.system.api.RemoteComLogisticsCompanyService;
+import org.dromara.system.api.domain.vo.RemoteLogisticsCompanyVo;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -30,6 +31,9 @@ import java.util.List;
 @RequestMapping("/api/thirdparty")
 public class ThirdpartyCommonController {
 
+    @DubboReference
+    private RemoteComLogisticsCompanyService remoteComLogisticsCompanyService;
+
     /**
      * 获取区域地址
      */
@@ -69,4 +73,14 @@ public class ThirdpartyCommonController {
         // TODO: 实现产品单位查询逻辑
         return R.ok();
     }
+
+    /**
+     * 物流公司查询
+     */
+    @Operation(summary = "物流公司查询")
+    @PostMapping("/system/getLogisticsCompany")
+    public R<List<ThirdpartyLogisticsCompanyDto>> getLogisticsCompany() {
+        List<RemoteLogisticsCompanyVo> remoteLogisticsCompanyVos = remoteComLogisticsCompanyService.selectLogisticsCompanyList();
+        return R.ok(BeanUtil.copyToList(remoteLogisticsCompanyVos, ThirdpartyLogisticsCompanyDto.class));
+    }
 }

+ 76 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/tongji/TongJiPullController.java

@@ -54,6 +54,7 @@ public class TongJiPullController {
     private static final String CLIENT_ID = "KFZOW9K7ix6";
     private static final String PRIVATE_KEY = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgkRuHZ2UkqHOv+TpwYFkccmIJpE4Tje63UFV++O1AxTKgCgYIKoEcz1UBgi2hRANCAASL+QeNJvix0bhOunIyO/s1as0aGkQ6am3rf/4eb17UOnJzVo6xvKOFPRA/5rG0rFggU5hYwe70ElN/xWT/Cy2g"; // 电商平台私钥
     private static final String TJ_PUBLIC_KEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAECeORp+9YlmSobsiULe0D1obWOxjTG4aAeufqhtXEwy9BhpbLKQjjifXHKcb92ozx0VBtt5Yt9E7U06+hc0x/tQ=="; // 同济公钥
+    private final String username = "20240316002";
     //测试环境
     // 同济地区查询接口地址(替换为真实域名)
 //    private static final String AREA_QUERY_URL = "https://supply-test.crrcgo.cc/mallapi/";
@@ -74,6 +75,7 @@ public class TongJiPullController {
         // 1. 校验业务请求参数(自身先校验,避免无效调用电商平台)
         //1 省级,2市级,3县级, 4区级
         //父级地址id	当查询省级时填0
+        log.info("同济地区查询 - 参数:{}", bo);
         if (bo.getLevel() == null || !List.of(1, 2, 3, 4).contains(bo.getLevel())) {
             throw new RuntimeException("级次(level)必填,且仅支持1/2/3/4");
         }
@@ -459,7 +461,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/detail")
     public OrderDetailVo mallOrderDetail(@RequestBody OrderDetailBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/detail", bo);
+        log.info("查询订单详情参数:{}",JSONUtil.toJsonStr(bo));
         OrderDetailVo orderDetailVo = parseZcResponse(responseDto, OrderDetailVo.class);
+        log.info("查询订单详情结果:{}", orderDetailVo);
         return orderDetailVo;
     }
 
@@ -467,7 +471,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/confirm")
     public GoodsUpdateVo mallOrderConfirm(@RequestBody OrderConfirmBo bo) throws ZhongcheException {
         ZCR responseDto = doZcPost("/api/mall/order/confirm", bo);
+        log.info("接单参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("接单结果:{}", zcr);
         return zcr;
     }
 
@@ -475,7 +481,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/goods/append")
     public GoodsUpdateVo mallOrderGoodsAppend(@RequestBody OrderGoodsAppendBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/goods/append", bo);
+        log.info("同步商品协商发货时间参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("同步商品协商发货时间结果:{}", zcr);
         return zcr;
     }
 
@@ -483,7 +491,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/reject")
     public GoodsUpdateVo mallOrderReject(@RequestBody OrderRejectBo bo) throws ZhongcheException {
         ZCR responseDto = doZcPost("/api/mall/order/reject", bo);
+        log.info("拒单参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("拒单结果:{}", zcr);
         return zcr;
     }
 
@@ -491,15 +501,20 @@ public class TongJiPullController {
     @PostMapping("/mall/order/deliver/goods")
     public ZhongCheOrderDeliverVo mallOrderDeliverGoods(@RequestBody ZhongCheOrderDeliverBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/deliver/goods", bo);
+        log.info("发货参数:{}",JSONUtil.toJsonStr(bo));
         ZhongCheOrderDeliverVo zcr = parseZcResponse(responseDto, ZhongCheOrderDeliverVo.class);
+        log.info("发货结果:{}", zcr);
         return zcr;
     }
 
     //TODO 5.3.6	查询待处理订单列表
     @PostMapping("/mall/order/pending/list")
-    public PendingOrderListVo mallOrderPendingList(@RequestBody ZCTokenBo bo) {
+    public PendingOrderListVo mallOrderPendingList(@RequestBody PendingOrderListBo bo) {
+        bo.setAccount(username);
         ZCR responseDto = doZcPost("/api/mall/order/pending/list", bo);
+        log.info("查询待处理订单列表参数:{}",JSONUtil.toJsonStr(bo));
         PendingOrderListVo zcr = parseZcResponse(responseDto, PendingOrderListVo.class);
+        log.info("查询待处理订单列表结果:{}", zcr);
         return zcr;
     }
 
@@ -507,7 +522,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/delivered/notice")
     public GoodsUpdateVo mallOrderDeliveredNotice(@RequestBody OrderDeliveredNoticeBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/delivered/notice", bo);
+        log.info("妥投通知参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("妥投通知结果:{}", zcr);
         return zcr;
     }
 
@@ -515,7 +532,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/query/outgoing")
     public OutgoingVo mallOrderQueryOutgoing(@RequestBody OutgoingQueryBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/query/outgoing", bo);
+        log.info("查询发货单信息参数:{}",JSONUtil.toJsonStr(bo));
         OutgoingVo zcr = parseZcResponse(responseDto, OutgoingVo.class);
+        log.info("查询发货单信息结果:{}", zcr);
         return zcr;
     }
 
@@ -523,7 +542,9 @@ public class TongJiPullController {
     @PostMapping("/mall/prepare/order/detail")
     public PrepareOrderDetailRespVo mallPrepareOrderDetail(@RequestBody PrepareOrderDetailReqBo bo) {
         ZCR responseDto = doZcPost("/api/mall/prepare/order/detail", bo);
+        log.info("查询备货单详情参数:{}",JSONUtil.toJsonStr(bo));
         PrepareOrderDetailRespVo zcr = parseZcResponse(responseDto, PrepareOrderDetailRespVo.class);
+        log.info("查询备货单详情结果:{}", zcr);
         return zcr;
     }
 
@@ -531,7 +552,9 @@ public class TongJiPullController {
     @PostMapping("/mall/prepare/order/goods")
     public GoodsUpdateVo mallPrepareOrderGoods(@RequestBody PrepareOrderDataBo bo) {
         ZCR responseDto = doZcPost("/api/mall/prepare/order/goods", bo);
+        log.info("备货参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("备货结果:{}", zcr);
         return zcr;
     }
 
@@ -540,7 +563,9 @@ public class TongJiPullController {
     @PostMapping("/mall/prepare/order/confirm/cancel")
     public GoodsUpdateVo mallPrepareOrderConfirmCancel(@RequestBody PrepareOrderDetailReqBo bo) {
         ZCR responseDto = doZcPost("/api/mall/prepare/order/confirm/cancel", bo);
+        log.info("确认取消备货单参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("确认取消备货单结果:{}", zcr);
         return zcr;
     }
 
@@ -556,7 +581,9 @@ public class TongJiPullController {
     @PostMapping("/mall/order/cancel/audit/judge")
     public GoodsUpdateVo mallOrderCancelAuditJudge(@RequestBody OrderCancelAuditBo bo) {
         ZCR responseDto = doZcPost("/api/mall/order/cancel/audit/judge", bo);
+        log.info("审核订单取消参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("审核订单取消结果:{}", zcr);
         return zcr;
     }
     //5.4.1	查询售后单详情
@@ -574,7 +601,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/detail")
     public AfterSaleDetailVo mallAftersaleDetail(@RequestBody AfterSaleDetailBo bo) {
         ZCR responseDto = doZcPost("/api/mall/aftersale/detail", bo);
+        log.info("查询售后单详情参数:{}",JSONUtil.toJsonStr(bo));
         AfterSaleDetailVo zcr = parseZcResponse(responseDto, AfterSaleDetailVo.class);
+        log.info("查询售后单详情结果:{}", zcr);
         return zcr;
     }
 
@@ -582,7 +611,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/confirm")
     public GoodsUpdateVo mallAftersaleConfirm(@RequestBody AfterSaleConfirmBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/confirm", bo);
+        log.info("接受售后参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("接受售后结果:{}", zcr);
         return zcr;
     }
 
@@ -590,7 +621,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/reject")
     public GoodsUpdateVo mallAftersaleReject(@RequestBody AfterSaleRejectBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/reject", bo);
+        log.info("拒绝售后参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("拒绝售后结果:{}", zcr);
         return zcr;
     }
 
@@ -598,7 +631,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/return/goods/received")
     public GoodsUpdateVo mallAftersaleReturnGoodsReceived(@RequestBody AfterSaleReturnReceivedBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/return/goods/received", bo);
+        log.info("确认收到退货参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("确认收到退货结果:{}", zcr);
         return zcr;
     }
 
@@ -606,7 +641,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/deliver/goods")
     public AfterSaleDeliverGoodsVo mallAftersaleDeliverGoods(@RequestBody AfterSaleDeliverGoodsBo bo) {
         ZCR responseDto = doZcPost("/api/mall/aftersale/deliver/goods", bo);
+        log.info("换货新品发货参数:{}",JSONUtil.toJsonStr(bo));
         AfterSaleDeliverGoodsVo zcr = parseZcResponse(responseDto, AfterSaleDeliverGoodsVo.class);
+        log.info("换货新品发货结果:{}", zcr);
         return zcr;
     }
 
@@ -614,7 +651,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/pending/list")
     public AfterSalePendingListVo mallAftersalePendingList(@RequestBody AfterSalePendingListBo bo) {
         ZCR responseDto = doZcPost("/api/mall/aftersale/pending/list", bo);
+        log.info("查询待处理售后单列表参数:{}",JSONUtil.toJsonStr(bo));
         AfterSalePendingListVo zcr = parseZcResponse(responseDto, AfterSalePendingListVo.class);
+        log.info("查询待处理售后单列表结果:{}", zcr);
         return zcr;
     }
 
@@ -622,7 +661,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/query/outgoing")
     public AfterSaleQueryOutgoingVo mallAftersaleQueryOutgoing(@RequestBody AfterSaleQueryOutgoingBo bo) {
         ZCR responseDto = doZcPost("/api/mall/aftersale/query/outgoing", bo);
+        log.info("查询换货新品发货单信息参数:{}",JSONUtil.toJsonStr(bo));
         AfterSaleQueryOutgoingVo zcr = parseZcResponse(responseDto, AfterSaleQueryOutgoingVo.class);
+        log.info("查询换货新品发货单信息结果:{}", zcr);
         return zcr;
     }
 
@@ -630,7 +671,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/offline/create")
     public AfterSaleOfflineCreateVo mallAftersaleOfflineCreate(@RequestBody AfterSaleOfflineCreateBo bo) {
         ZCR responseDto = doZcPost("/api/mall/aftersale/offline/create", bo);
+        log.info("线下售后参数:{}",JSONUtil.toJsonStr(bo));
         AfterSaleOfflineCreateVo zcr = parseZcResponse(responseDto, AfterSaleOfflineCreateVo.class);
+        log.info("线下售后结果:{}", zcr);
         return zcr;
     }
 
@@ -638,7 +681,9 @@ public class TongJiPullController {
     @PostMapping("/mall/aftersale/refund")
     public GoodsUpdateVo mallAftersaleRefund(@RequestBody AfterSaleRefundBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/refund", bo);
+        log.info("确认退款参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("确认退款结果:{}", zcr);
         return zcr;
     }
 
@@ -647,7 +692,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/apply/detail")
     public InvoiceApplyDetailVo mallInvoiceApplyDetail(@RequestBody InvoiceApplyDetailBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/apply/detail", bo);
+        log.info("查询开票信息参数:{}",JSONUtil.toJsonStr(bo));
         InvoiceApplyDetailVo zcr = parseZcResponse(responseDto, InvoiceApplyDetailVo.class);
+        log.info("查询开票信息结果:{}", zcr);
         return zcr;
 
     }
@@ -656,7 +703,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/apply/orders")
     public InvoiceApplyOrdersVo mallInvoiceApplyOrders(@RequestBody InvoiceApplyOrdersBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/apply/orders", bo);
+        log.info("查询开票申请订单列表参数:{}",JSONUtil.toJsonStr(bo));
         InvoiceApplyOrdersVo zcr = parseZcResponse(responseDto, InvoiceApplyOrdersVo.class);
+        log.info("查询开票申请订单列表结果:{}", zcr);
         return zcr;
 
     }
@@ -665,7 +714,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/apply/reject")
     public GoodsUpdateVo mallInvoiceApplyReject(@RequestBody InvoiceApplyRejectBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/apply/reject", bo);
+        log.info("拒绝开票参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("拒绝开票结果:{}", zcr);
         return zcr;
     }
 
@@ -673,7 +724,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/sync/invoiceinfos")
     public GoodsUpdateVo mallInvoiceSyncInvoiceInfos(@RequestBody InvoiceSyncInvoiceInfosBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/sync/invoiceinfos", bo);
+        log.info("电商同步开票信息参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("电商同步开票信息结果:{}", zcr);
         return zcr;
     }
 
@@ -682,7 +735,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/sync/waybill")
     public GoodsUpdateVo mallInvoiceSyncWaybill(@RequestBody InvoiceSyncWaybillBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/sync/waybill", bo);
+        log.info("同步纸质发票邮寄信息参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("同步纸质发票邮寄信息结果:{}", zcr);
         return zcr;
     }
 
@@ -690,7 +745,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/delivered/notice")
     public GoodsUpdateVo mallInvoiceDeliveredNotice(@RequestBody InvoiceDeliveredNoticeBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/delivered/notice", bo);
+        log.info("发票妥投通知参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("发票妥投通知结果:{}", zcr);
         return zcr;
     }
 
@@ -698,7 +755,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/apply/waitlist")
     public InvoiceApplyWaitlistVo mallInvoiceApplyWaitList(@RequestBody InvoiceApplyWaitlistBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/apply/waitlist", bo);
+        log.info("查询待开票申请单列表参数:{}",JSONUtil.toJsonStr(bo));
         InvoiceApplyWaitlistVo zcr = parseZcResponse(responseDto, InvoiceApplyWaitlistVo.class);
+        log.info("查询待开票申请单列表结果:{}", zcr);
         return zcr;
     }
 
@@ -706,7 +765,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/refund/agree")
     public GoodsUpdateVo mallInvoiceRefundAgree(@RequestBody InvoiceRefundAgreeBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/refund/agree", bo);
+        log.info("电商同意退票参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("电商同意退票结果:{}", zcr);
         return zcr;
     }
 
@@ -715,7 +776,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/refund/finish")
     public GoodsUpdateVo mallInvoiceRefundFinish(@RequestBody InvoiceRefundFinishBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/refund/finish", bo);
+        log.info("电商确认完成退票参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("电商确认完成退票结果:{}", zcr);
         return zcr;
     }
 
@@ -723,7 +786,9 @@ public class TongJiPullController {
     @PostMapping("/mall/invoice/refund/reject")
     public GoodsUpdateVo mallInvoiceRefundReject(@RequestBody InvoiceRefundRejectBo bo) {
         ZCR responseDto = doZcPost("/api/mall/invoice/refund/reject", bo);
+        log.info("电商拒绝退票申请参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo goodsUpdateVo = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("电商拒绝退票申请结果:{}", goodsUpdateVo);
         return goodsUpdateVo;
     }
 
@@ -731,7 +796,9 @@ public class TongJiPullController {
     @PostMapping("/mall/settlement/detail")
     public SettlementDetailVo mallSettlementDetail(@RequestBody SettlementDetailBo bo) {
         ZCR responseDto = doZcPost("/api/mall/settlement/detail", bo);
+        log.info("查询结算单详情参数:{}",JSONUtil.toJsonStr(bo));
         SettlementDetailVo settlementDetailVo = parseZcResponse(responseDto, SettlementDetailVo.class);
+        log.info("查询结算单详情结果:{}", settlementDetailVo);
         return settlementDetailVo;
     }
 
@@ -739,7 +806,9 @@ public class TongJiPullController {
     @PostMapping("/mall/settlement/apply/orders")
     public SettlementApplyOrdersVo mallSettlementApplyOrders(@RequestBody SettlementApplyOrdersBo bo) {
         ZCR responseDto = doZcPost("/api/mall/settlement/apply/orders", bo);
+        log.info("查询结算单订单列表参数:{}",JSONUtil.toJsonStr(bo));
         SettlementApplyOrdersVo settlementApplyOrdersVo = parseZcResponse(responseDto, SettlementApplyOrdersVo.class);
+        log.info("查询结算单订单列表结果:{}", settlementApplyOrdersVo);
         return settlementApplyOrdersVo;
     }
 
@@ -748,7 +817,9 @@ public class TongJiPullController {
     @PostMapping("/mall/settlement/confirm")
     public GoodsUpdateVo mallSettlementConfirm(@RequestBody SettlementConfirmBo bo) {
         ZCR responseDto = doZcPost("/api/mall/settlement/confirm", bo);
+        log.info("结算单确认结算参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo goodsUpdateVo = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("结算单确认结算结果:{}", goodsUpdateVo);
         return goodsUpdateVo;
     }
 
@@ -756,7 +827,9 @@ public class TongJiPullController {
     @PostMapping("/mall/settlement/payment/detail")
     public SettlementPaymentDetailVo mallSettlementPaymentDetail( @RequestBody SettlementPaymentDetailBo bo) {
         ZCR responseDto = doZcPost("/api/mall/settlement/payment/detail", bo);
+        log.info("结算单付款详情参数:{}",JSONUtil.toJsonStr(bo));
         SettlementPaymentDetailVo settlementPaymentDetailVo = parseZcResponse(responseDto, SettlementPaymentDetailVo.class);
+        log.info("结算单付款详情结果:{}", settlementPaymentDetailVo);
         return settlementPaymentDetailVo;
 
     }
@@ -765,7 +838,9 @@ public class TongJiPullController {
     @PostMapping("/mall/settlement/confirm/payment")
     public GoodsUpdateVo mallSettlementConfirmPayment( @RequestBody SettlementConfirmPaymentBo bo) {
         ZCR responseDto = doZcPost("/api/mall/settlement/confirm/payment", bo);
+        log.info("结算单确认收款参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo goodsUpdateVo = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("结算单确认收款结果:{}", goodsUpdateVo);
         return goodsUpdateVo;
     }
 

+ 30 - 22
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/tongji/TongJiPushController.java

@@ -23,7 +23,7 @@ import org.dromara.external.api.zhongche.domain.Stocks;
 import org.dromara.external.api.zhongche.domain.ZCR;
 import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
-import org.dromara.external.controller.zhongche.handle.MallMessageDispatcher;
+import org.dromara.external.handler.MallMessageDispatcher;
 import org.dromara.external.domain.ExternalItem;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.ExternalProductCategory;
@@ -148,10 +148,10 @@ public class TongJiPushController {
             // 步骤6.3:用电商私钥生成SM2签名(Base64编码,直接赋值给sign)
             respSign = SM2SignatureUtils.sign(respSignContent, DEVELOPER_PRIVATE_KEY);
         } catch (JsonProcessingException e) {
-            log.error("同济电商品目查询接口 - 待签名字符串生成失败,业务JSON:{}", respBizJson, e);
+            log.error("中车电商品目查询接口 - 待签名字符串生成失败,业务JSON:{}", respBizJson, e);
             return ZCR.fail("5009", "接口响应签名生成异常(JSON转换失败)");
         } catch (Exception e) {
-            log.error("同济电商品目查询接口 - 响应签名生成失败,业务JSON:{}", respBizJson, e);
+            log.error("中车电商品目查询接口 - 响应签名生成失败,业务JSON:{}", respBizJson, e);
             return ZCR.fail("5010", "接口响应签名生成失败,请稍后重试");
         }
         // 7. 封装最终响应(严格复用你的ZCR.resetR)
@@ -159,7 +159,7 @@ public class TongJiPushController {
     }
 
     /**
-     * 数据库实体 → 同济品目VO(ProductCategory字段)
+     * 数据库实体 → 中车品目VO(ProductCategory字段)
      */
     private Catalog convertToCatalogVo(ProductCategoryRemoteVo category) {
         Catalog catalog = new Catalog();
@@ -298,13 +298,13 @@ public class TongJiPushController {
 
         // 2. 提取商品ID列表,准备查询库存
         List<String> goodsIds = goodsMap.keySet().stream().collect(Collectors.toList());
-        ExternalItem one = externalItemService.getOne(Wrappers.lambdaQuery(ExternalItem.class).eq(ExternalItem::getItemKey, "zhongche").last("LIMIT 1"));
+        ExternalItem one = externalItemService.getOne(Wrappers.lambdaQuery(ExternalItem.class).eq(ExternalItem::getItemKey, "tongji").last("LIMIT 1"));
         List<ExternalProduct> externalProducts = externalProductService.queryProductStock(one.getId(),goodsIds);
         // 5. 遍历查询结果,封装返回数据
         externalProducts.forEach(product -> {
             // 5.1 提取商品核心信息
             String productIdStr = product.getProductNo();
-            Integer nowInventory = product.getAvailableInventory();
+            Integer nowInventory = ObjectUtil.isEmpty(product.getAvailableInventory()) ? 0 : product.getAvailableInventory();
             Integer goodsNum = goodsMap.get(productIdStr); // 入参的所需库存数量
             //可用库存
 
@@ -315,15 +315,17 @@ public class TongJiPushController {
             stocksResult.setAreaId(areaId == null ? "" : areaId); // 地区id为空时赋值空字符串,保证格式统一
 
             if (nowInventory > 0){
-                //有货
-                stocksResult.setStockState("1");
-                stocksResult.setStockStateDesc("下单立即发货");
-                if (goodsNum < 50){
+
+                if (goodsNum <= nowInventory){
+                    //有货
+                    stocksResult.setStockState("1");
+                    stocksResult.setStockStateDesc("下单立即发货");
                     stocksResult.setRemainNum(nowInventory.intValue());
-                }else if (goodsNum <= 100){
-                    stocksResult.setRemainNum(-1);
                 }else {
-                    stocksResult.setRemainNum(goodsNum);
+                    //无货
+                    stocksResult.setStockState("5");
+                    stocksResult.setStockStateDesc("无货");
+                    stocksResult.setRemainNum(-999);
                 }
             }else {
                 //无货
@@ -432,6 +434,12 @@ public class TongJiPushController {
      * 核心业务:查询商品价格,映射文档返回格式
      */
     public PricesVo queryGoodsPrice(List<String> goodsIdList) {
+        //获取项目配置
+        ExternalItem externalItem = externalItemService.getOne(
+            Wrappers.lambdaQuery(ExternalItem.class)
+                .eq(ExternalItem::getItemKey, "tongji")
+                .last("LIMIT 1")
+        );
         // 1. 初始化响应结果
         PricesVo pricesVo = new PricesVo();
         pricesVo.setPrices(new ArrayList<>());
@@ -452,8 +460,6 @@ public class TongJiPushController {
                 priceResp.setDsPrice(new BigDecimal(-1));
                 priceResp.setPrice(new BigDecimal(-1));
                 priceResp.setTaxFreePrice(null);
-                priceResp.setTax(BigDecimal.valueOf(0.13));
-                priceResp.setTaxCode("107022301");
                 pricesVo.getPrices().add(priceResp);
                 continue;
             }
@@ -466,6 +472,7 @@ public class TongJiPushController {
             // 协议价格(price)
             ExternalProduct one = externalProductService.getOne(new LambdaQueryWrapper<>(ExternalProduct.class)
                 .eq(ExternalProduct::getProductNo, goodsId)
+                .eq(ExternalProduct::getItemId, externalItem.getId())
                 .last("LIMIT 1")
             );
             if (one == null) {
@@ -476,10 +483,8 @@ public class TongJiPushController {
                 // 找到协议价格,使用数据库中的协议价格
                 priceResp.setPrice(one.getExternalPrice());
             }
-            priceResp.setTaxFreePrice(null);
-            priceResp.setTax(BigDecimal.valueOf(0.13));
             // 税收编码(非必填)
-            priceResp.setTaxCode("107022301");
+            priceResp.setTaxCode(one.getTaxCode());
             // 3.3 添加到响应列表
             pricesVo.getPrices().add(priceResp);
         }
@@ -496,6 +501,7 @@ public class TongJiPushController {
     // 4.5查询物流信息(物流信息尚未实现)
     @PostMapping("/get/track")
     public ZCR getTrack(@RequestBody ZCTokenBo zcTokenBo) {
+        log.info("物流信息查询 - 接口请求参数:{}", JSONUtil.toJsonStr(zcTokenBo));
         // 1. 公共请求参数校验(含签名、版本、clientId等,复用已有逻辑)
         ZCR checkResult = checkPublicParams(zcTokenBo);
         if (!"0".equals(checkResult.getRespCode())) {
@@ -561,6 +567,7 @@ public class TongJiPushController {
     //4.6 查询电商平台订单号
     @PostMapping("/get/mallOrderNo")
     public ZCR getMallOrderNo(@RequestBody ZCTokenBo zcTokenBo) {
+        log.info("查询电商订单号 - 请求参数:{}", JSONUtil.toJsonStr(zcTokenBo));
         //1. 公共请求参数校验
         ZCR checkResult = checkPublicParams(zcTokenBo);
         if (!"0".equals(checkResult.getRespCode())) {
@@ -571,7 +578,7 @@ public class TongJiPushController {
         try {
             verifyResult = SignParamUtils.verifyRequestSign(
                 zcTokenBo,
-                DEVELOPER_PUBLIC_KEY   // 同济给你的公钥
+                DEVELOPER_PUBLIC_KEY   // 中车给你的公钥
             );
         } catch (Exception e) {
             log.error("查询电商订单号 - 请求验签异常", e);
@@ -628,6 +635,7 @@ public class TongJiPushController {
     //4.7 查询电商平台售后单号
     @PostMapping("/get/mallAfterSaleNo")
     public ZCR getMallAfterSaleNo(@RequestBody ZCTokenBo zcTokenBo) {
+        log.info("查询售后单号 - 请求参数:{}", JSONUtil.toJsonStr(zcTokenBo));
         // 1. 公共请求参数校验
         ZCR checkResult = checkPublicParams(zcTokenBo);
         if (!"0".equals(checkResult.getRespCode())) {
@@ -724,7 +732,7 @@ public class TongJiPushController {
         // 5. 按消息类型处理业务
         MessageVo messageVo;
         try {
-            messageBo.setItemKey("zhongche");
+            messageBo.setItemKey("tongji");
             messageVo = mallMessageDispatcher.dispatch(messageBo);
         } catch (Exception e) {
             log.error("消息处理异常,messageId={}", messageBo.getId(), e);
@@ -869,7 +877,7 @@ public class TongJiPushController {
             }
         } catch (Exception e) {
             // 捕获验签过程中的异常(如JSON转换、Base64解码、SM2算法异常等)
-            log.error("同济电商接口签名校验异常,请求参数:{}", JSONUtil.toJsonStr(zcTokenBo), e);
+            log.error("中车电商接口签名校验异常,请求参数:{}", JSONUtil.toJsonStr(zcTokenBo), e);
             return ZCR.fail("5007", "接口签名校验异常,请稍后重试");
         }
 
@@ -903,7 +911,7 @@ public class TongJiPushController {
         bo.setAccessToken( "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoyMDM3MDc2OTc3MjQ2MzE0NDk3Iiwicm5TdHIiOiJVTm84azZISzFLQXZ0eXJZOG9KZUtZV0dQbHd1MnlMZCIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MjAzNzA3Njk3NzI0NjMxNDQ5NywidXNlck5hbWUiOiIyMDI0MDMxNjAwMSIsImRlcHRJZCI6MTk5NjgyODcyMjQwMDg5OTA3NCwiZGVwdE5hbWUiOiJBUEnlr7nmjqXnrqHnkIblubPlj7AiLCJkZXB0Q2F0ZWdvcnkiOiIifQ.BSrQtYQQIcy2chvcza4qVjj7x6wXw2OA5zAJb0vI-rk");
         // 注意:此时不要 setSign
 
-        // 2️⃣ 打印待签名内容(用于和同济排查)
+        // 2️⃣ 打印待签名内容(用于和中车排查)
         String signContent = SignParamUtils.getSignContent(bo);
         System.out.println("待签名字符串:");
         System.out.println(signContent);

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java

@@ -48,7 +48,7 @@ import java.util.List;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/api")
+@RequestMapping("/zhongche/api")
 public class ZhongChePullController {
 
     //正式环境

+ 3 - 5
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java

@@ -25,7 +25,7 @@ import org.dromara.external.api.zhongche.domain.bo.AreaStockBo;
 import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.api.zhongche.domain.Catalog;
-import org.dromara.external.controller.zhongche.handle.MallMessageDispatcher;
+import org.dromara.external.handler.MallMessageDispatcher;
 import org.dromara.external.domain.ExternalItem;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.ExternalProductCategory;
@@ -58,7 +58,7 @@ import static org.dromara.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/api/mall")
+@RequestMapping("/zhongche/api/mall")
 public class ZhongChePushController {
     private final String key = GLOBAL_REDIS_KEY+"external:zhongche:token:";
     private final String CLIENT_ID = "KFZnKGiDsJ7";
@@ -307,7 +307,7 @@ public class ZhongChePushController {
         externalProducts.forEach(product -> {
             // 5.1 提取商品核心信息
             String productIdStr = product.getProductNo();
-            Integer nowInventory = product.getAvailableInventory();
+            Integer nowInventory = ObjectUtil.isEmpty(product.getAvailableInventory()) ? 0 : product.getAvailableInventory();
             Integer goodsNum = goodsMap.get(productIdStr); // 入参的所需库存数量
             //可用库存
 
@@ -457,8 +457,6 @@ public class ZhongChePushController {
                 priceResp.setDsPrice(new BigDecimal(-1));
                 priceResp.setPrice(new BigDecimal(-1));
                 priceResp.setTaxFreePrice(null);
-                priceResp.setTax(BigDecimal.valueOf(0.13));
-                priceResp.setTaxCode("107022301");
                 pricesVo.getPrices().add(priceResp);
                 continue;
             }

+ 0 - 202
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/OrderCreateMessageHandler.java

@@ -1,202 +0,0 @@
-package org.dromara.external.controller.zhongche.handle.impl;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.dubbo.config.annotation.DubboReference;
-import org.dromara.common.core.domain.zhongche.domain.OrderGoodsItem;
-import org.dromara.common.core.domain.zhongche.domain.ZhongCheOrderInvoice;
-import org.dromara.common.core.domain.zhongche.vo.OrderDetailVo;
-import org.dromara.external.api.zhongche.domain.bo.AreaQueryBo;
-import org.dromara.external.api.zhongche.domain.bo.MessageBo;
-import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
-import org.dromara.external.api.zhongche.domain.bo.OrderDetailBo;
-import org.dromara.external.api.zhongche.domain.vo.AreaVo;
-import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
-import org.dromara.external.api.zhongche.domain.vo.MessageVo;
-import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
-import org.dromara.external.domain.ExternalItem;
-import org.dromara.external.domain.ExternalProduct;
-import org.dromara.external.enums.MallMessageTypeEnum;
-import org.dromara.external.mapper.ExternalProductMapper;
-import org.dromara.external.service.IExternalItemService;
-import org.dromara.external.service.IExternalProductService;
-import org.dromara.product.api.RemoteExternalOrderService;
-import org.dromara.product.api.domain.dto.OrderNoDto;
-import org.springframework.stereotype.Component;
-import org.dromara.external.api.zhongche.domain.Area;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import java.math.BigDecimal;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-@Component
-@Slf4j
-@RequiredArgsConstructor
-public class OrderCreateMessageHandler implements MallMessageHandler {
-
-    private final ZhongChePullController zhongChePullController;
-
-    private final IExternalProductService externalProductService;
-
-    private final IExternalItemService externalItemService;
-
-    @DubboReference
-    private final RemoteExternalOrderService remoteExternalOrderService;
-
-    @Override
-    public MallMessageTypeEnum supportType() {
-        return MallMessageTypeEnum.ORDER_CREATE;
-    }
-
-
-    /*@Override
-    public MessageVo handle(MessageBo messageBo) {
-        //获取中车订单号获取订单详情,我们电商平台没有接单功能胡哥说的,然后默认接单 就发起接单的请求
-        String orderNo = (String) messageBo.getContent().get("orderNo");
-        log.info("处理新订单消息,orderNo={}", orderNo);
-        OrderDetailBo orderDetailBo = new OrderDetailBo();
-        orderDetailBo.setOrderNo(orderNo);
-        OrderDetailVo orderDetailVo = zhongChePullController.mallOrderDetail(orderDetailBo);
-        OrderNoDto orderNoDto = remoteExternalOrderService.createZhongCheOrder(orderDetailVo);
-        if (orderNoDto.getSuccess()){
-            return new MessageVo("1");
-        }else {
-            return new MessageVo("0","获取订单详情失败");
-        }
-    }*/
-
-
-    @Override
-    public MessageVo handle(MessageBo messageBo) {
-        //获取中车订单号获取订单详情,我们电商平台没有接单功能胡哥说的,然后默认接单 就发起接单的请求
-        log.info("处理新订单消息参数,messageBo={}", JSONUtil.toJsonStr(messageBo));
-        String orderNo = (String) messageBo.getContent().get("orderNo");
-        OrderDetailBo orderDetailBo = new OrderDetailBo();
-        orderDetailBo.setOrderNo(orderNo);
-        OrderDetailVo orderDetailVo = zhongChePullController.mallOrderDetail(orderDetailBo);
-        orderDetailVo.setDataSource(messageBo.getItemKey());
-//        OrderDetailVo orderDetailVo = new OrderDetailVo();
-//
-//// ===== 基本信息 =====
-//        orderDetailVo.setOrderNo("20260210110174145");
-//        orderDetailVo.setPurchaserOrderNo("2026021010452505");
-//        orderDetailVo.setPreOrder(0);
-//        orderDetailVo.setMallOrderNo(null);
-//        orderDetailVo.setOrderStatus("1");
-//        orderDetailVo.setOrderAmount(new BigDecimal("205.24"));
-//        orderDetailVo.setFreight(new BigDecimal("0.00"));
-//
-//// ===== 收货信息 =====
-//        orderDetailVo.setName("111");
-//        orderDetailVo.setProvinceId("1");
-//        orderDetailVo.setCityId("2800");
-//        orderDetailVo.setCountyId("55835");
-//        orderDetailVo.setTownId("0");
-//        orderDetailVo.setAddress("中车智程");
-//        orderDetailVo.setZip(null);
-//        orderDetailVo.setMobile("13381115928");
-//        orderDetailVo.setPhone(null);
-//        orderDetailVo.setEmail("service_yg@bosssoft.com.cn");
-//
-//// ===== 下单信息 =====
-//        orderDetailVo.setMemo("");
-//        orderDetailVo.setOrderTime("2026-02-10 17:25:18");
-//        orderDetailVo.setBuyer("常恒瑀");
-//        orderDetailVo.setBuyerMobile("18801195315");
-//        orderDetailVo.setPurchaserName("中国中车");
-//        orderDetailVo.setPurchaserDeptName("中国中车-中车科技园发展有限公司-中车智程文化科技(北京)有限公司");
-//
-//// ===== 支付信息 =====
-//        orderDetailVo.setPaymentType("01");
-//        orderDetailVo.setVoucher("0");
-//        orderDetailVo.setPayClient("0");
-//        orderDetailVo.setPaySerialNum(null);
-//        orderDetailVo.setPayAccount(null);
-//        orderDetailVo.setPayMoney(null);
-//        orderDetailVo.setPayPrestore(null);
-//
-//        OrderGoodsItem goodsItem = new OrderGoodsItem();
-//        goodsItem.setGoodsId("362032");
-//        goodsItem.setNum(new BigDecimal("7.0000"));
-//        goodsItem.setPrice(new BigDecimal("29.3200"));
-//        goodsItem.setSubAmount(new BigDecimal("205.24"));
-//        goodsItem.setWishDeliveryDate(null);
-//
-//        orderDetailVo.setOrderGoods(Collections.singletonList(goodsItem));
-//        ZhongCheOrderInvoice invoice = new ZhongCheOrderInvoice();
-//        invoice.setInvoiceType("2");
-//        invoice.setSelectedInvoiceTitle("5");
-//        invoice.setCompanyName("中车智程文化科技(北京)");
-//        invoice.setInvoiceContent("1");
-//        invoice.setInvoiceName("王琳");
-//        invoice.setInvoicePhone("15249101907");
-//        invoice.setInvoiceFullAddress("北京海淀区羊坊店街道北京市海淀区羊坊店路11号");
-//        invoice.setRegCompanyName("中车智程文化科技(北京)");
-//        invoice.setRegCode("91110108MAC4385K6J");
-//        invoice.setRegAddr("北京市海淀区羊坊店路11号四层428室测试");
-//        invoice.setRegPhone("010-51891021");
-//        invoice.setRegBank("中国工商银行股份有限公司北京玉渊潭支行测试");
-//        invoice.setRegBankAccount("111111111");
-//        orderDetailVo.setOrderInvoice(invoice);
-        //获取省市区乡的名称
-        //省
-        AreaQueryBo provinceNameAreaQueryBo = new AreaQueryBo();
-        provinceNameAreaQueryBo.setLevel(1);
-        provinceNameAreaQueryBo.setPid("0");
-        AreaVo provinceNameAreaVo = zhongChePullController.areaQuery(provinceNameAreaQueryBo);
-        Map<String, String> provinceNameMap = provinceNameAreaVo.getAreas().stream().collect(Collectors.toMap(Area::getId, Area::getName));
-        //市
-        AreaQueryBo cityNameAreaQueryBo = new AreaQueryBo();
-        cityNameAreaQueryBo.setLevel(2);
-        cityNameAreaQueryBo.setPid(orderDetailVo.getProvinceId());
-        AreaVo cityNameAreaVo = zhongChePullController.areaQuery(cityNameAreaQueryBo);
-        Map<String, String> cityNameMap = cityNameAreaVo.getAreas().stream().collect(Collectors.toMap(Area::getId, Area::getName));
-        //区
-        AreaQueryBo countyNameAreaQueryBo = new AreaQueryBo();
-        countyNameAreaQueryBo.setLevel(3);
-        countyNameAreaQueryBo.setPid(orderDetailVo.getCityId());
-        AreaVo countyNameAreaVo = zhongChePullController.areaQuery(countyNameAreaQueryBo);
-        Map<String, String> countyNameMap = countyNameAreaVo.getAreas().stream().collect(Collectors.toMap(Area::getId, Area::getName));
-        //乡
-        AreaQueryBo townNameAreaQueryBo = new AreaQueryBo();
-        townNameAreaQueryBo.setLevel(4);
-        townNameAreaQueryBo.setPid(orderDetailVo.getCountyId());
-        AreaVo townNameAreaVo = zhongChePullController.areaQuery(townNameAreaQueryBo);
-        Map<String, String> townNameMap = townNameAreaVo.getAreas().stream().collect(Collectors.toMap(Area::getId, Area::getName));
-
-        orderDetailVo.setProvinceName(provinceNameMap.get(orderDetailVo.getProvinceId()));
-        orderDetailVo.setCityName(cityNameMap.get(orderDetailVo.getCityId()));
-        orderDetailVo.setCountyName(countyNameMap.get(orderDetailVo.getCountyId()));
-        orderDetailVo.setTownName(townNameMap.get(orderDetailVo.getTownId()));
-        OrderNoDto orderNoDto = remoteExternalOrderService.createZhongCheOrder(orderDetailVo);
-        log.info("新订单执行结果,orderNoDto={}", JSONUtil.toJsonStr(orderNoDto));
-        if (orderNoDto.getSuccess()){
-            List<OrderGoodsItem> orderGoods = orderDetailVo.getOrderGoods();
-            ExternalItem externalItem = externalItemService.getOne(Wrappers.lambdaQuery(ExternalItem.class).eq(ExternalItem::getItemKey, messageBo.getItemKey()));
-            //更新商品库存
-            for (OrderGoodsItem orderGoodsItem : orderGoods) {
-                ExternalProduct one = externalProductService.getOne(Wrappers.<ExternalProduct>lambdaQuery().
-                    eq(ExternalProduct::getProductNo, orderGoodsItem.getGoodsId())
-                    .eq(ExternalProduct::getItemId, ObjectUtil.isNotEmpty(externalItem)?externalItem.getId():"2028409445955592193")
-                );
-                one.setAvailableInventory(one.getAvailableInventory()-orderGoodsItem.getNum().intValue());
-                externalProductService.updateById(one);
-            }
-
-
-            return new MessageVo("1");
-        }else {
-            return new MessageVo("0","获取订单详情失败");
-        }
-    }
-
-
-
-}

+ 8 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalItemServiceImpl.java

@@ -11,6 +11,9 @@ import org.dromara.external.domain.vo.ExternalItemVo;
 import org.dromara.external.service.IExternalItemService;
 import org.springframework.stereotype.Service;
 
+import java.util.Map;
+import java.util.Set;
+
 /**
  * @author
  * @date 2026/1/14 下午5:02
@@ -36,4 +39,9 @@ public class RemoteExternalItemServiceImpl implements RemoteExternalItemService
         }
         return BeanUtil.toBean(externalItemVo, ExternalItemDto.class);
     }
+
+    @Override
+    public Map<String, String> selectItemNameByItemKeys(Set<String> itemKeys) {
+        return externalItemService.selectItemNameByItemKeys(itemKeys);
+    }
 }

+ 3 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalProductServiceImpl.java

@@ -83,7 +83,9 @@ public class RemoteExternalProductServiceImpl implements RemoteExternalProductSe
             //不存在则新增存在则跳过
             if(Objects.equals(product.getType(),0)){
                 if (!externalProductService.exists(Wrappers.lambdaQuery(ExternalProduct.class)
-                    .eq(ExternalProduct::getProductId, product.getProductId()))){
+                    .eq(ExternalProduct::getProductId, product.getProductId())
+                    .eq(ExternalProduct::getItemId, product.getItemId())
+                )){
                     ExternalProduct externalProduct = BeanUtil.toBean(product, ExternalProduct.class);
                     externalProductService.save(externalProduct);
                 }

+ 32 - 3
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteTongJiPullServiceImpl.java

@@ -7,13 +7,14 @@ import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleConfirmBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleRefundBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleRejectBo;
 import org.dromara.common.core.domain.zhongche.aftersale.bo.AfterSaleReturnReceivedBo;
+import org.dromara.common.core.domain.zhongche.vo.OrderDetailVo;
 import org.dromara.common.core.exception.api.ZhongcheException;
 import org.dromara.external.api.tongji.RemoteTongJiPullService;
 
-import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
-import org.dromara.external.api.zhongche.domain.bo.OrderRejectBo;
-import org.dromara.external.api.zhongche.domain.bo.ZhongCheOrderDeliverBo;
+import org.dromara.external.api.zhongche.domain.bo.*;
+import org.dromara.external.api.zhongche.domain.vo.AreaVo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
+import org.dromara.external.api.zhongche.domain.vo.PendingOrderListVo;
 import org.dromara.external.api.zhongche.domain.vo.ZhongCheOrderDeliverVo;
 import org.dromara.external.controller.tongji.TongJiPullController;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
@@ -30,6 +31,16 @@ import org.springframework.stereotype.Service;
 public class RemoteTongJiPullServiceImpl implements RemoteTongJiPullService {
 
     private final TongJiPullController tongJiPullController;
+    /**
+     * @param bo
+     * @return
+     */
+    @Override
+    public AreaVo areaQuery(AreaQueryBo bo) {
+        AreaVo areaVo = tongJiPullController.areaQuery(bo);
+        return areaVo;
+    }
+
     @Override
     public GoodsUpdateVo mallOrderConfirm(OrderConfirmBo bo) throws ZhongcheException {
         GoodsUpdateVo goodsUpdateVo = tongJiPullController.mallOrderConfirm(bo);
@@ -72,4 +83,22 @@ public class RemoteTongJiPullServiceImpl implements RemoteTongJiPullService {
     public ZhongCheOrderDeliverVo mallOrderDeliverGoods(ZhongCheOrderDeliverBo bo) throws ZhongcheException {
         return tongJiPullController.mallOrderDeliverGoods(bo);
     }
+
+    /**
+     * @param bo
+     * @return
+     */
+    @Override
+    public PendingOrderListVo mallOrderPendingList(PendingOrderListBo bo) {
+        return tongJiPullController.mallOrderPendingList(bo);
+    }
+
+    /**
+     * @param bo
+     * @return
+     */
+    @Override
+    public OrderDetailVo mallOrderDetail(OrderDetailBo bo) {
+        return tongJiPullController.mallOrderDetail(bo);
+    }
 }

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/MallMessageDispatcher.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/MallMessageDispatcher.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle;
+package org.dromara.external.handler;
 
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/MallMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/MallMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle;
+package org.dromara.external.handler;
 
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;

+ 6 - 4
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java

@@ -3,10 +3,12 @@ package org.dromara.external.handler;
 import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.domain.ExternalProduct;
+import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.product.api.domain.ProductVo;
 
 import java.util.List;
+import java.util.Map;
 
 public interface ProductPushStrategy {
 
@@ -18,7 +20,7 @@ public interface ProductPushStrategy {
     /**
      * 商品价格变更
      */
-    GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products);
+    GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products , Map<String, ExternalProduct> externalProductMap);
 
     /**
      * 商品上下架状态变更
@@ -28,15 +30,15 @@ public interface ProductPushStrategy {
     /**
      * 商品图片变更
      */
-    GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products);
+    GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap);
 
     /**
      * 商品规格信息变更
      */
-    GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products);
+    GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap);
 
     /**
      * 商品详情信息变更
      */
-    GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products);
+    GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap,Map<Long, ExternalProductCategory> productCategoryMap);
 }

+ 65 - 31
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/TongjiPushStrategy.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/TongjiPushStrategy.java

@@ -1,6 +1,8 @@
-package org.dromara.external.handler.impl;
+package org.dromara.external.handler;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -20,7 +22,6 @@ import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.domain.ExternalPushPoolLog;
 import org.dromara.external.domain.vo.ExternalProductVo;
-import org.dromara.external.handler.ProductPushStrategy;
 import org.dromara.external.mapper.ExternalProductMapper;
 import org.dromara.external.service.IExternalProductCategoryService;
 import org.dromara.external.service.IExternalPushPoolLogService;
@@ -44,7 +45,7 @@ import java.util.stream.Collectors;
 @Slf4j
 public class TongjiPushStrategy  implements ProductPushStrategy {
 
-    private final String username = "20240316001";
+    private final String username = "20240316002";
 
     @DubboReference
     private final RemoteProductService remoteProductService;
@@ -74,6 +75,7 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
             item.setProductStatus(externalProductVo.getProductStatus());
             item.setMemberPrice(productDetail.getMemberPrice());
             item.setProductImage(productDetail.getImageUrl());
+            item.setTaxRate(productDetail.getTaxRate());
         });
 
         // 收集所有 externalCategoryId
@@ -174,26 +176,52 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
                 goodsImportItem.setDescription(productAggregateMap.get(item.getProductId()).getDescription());
 
                 //TODO 商品规格  默认 颜色:白色
-//            if (StringUtils.isNotBlank(productAggregateMap.get(item.getProductId()).getDiyAttributesList())) {
-//                String diyAttributesList = productAggregateMap.get(item.getProductId()).getDiyAttributesList();
-//                List<Map> list = JSONUtil.toList(diyAttributesList, Map.class);
-//                //格式为[{attributeKey:"",attributeValue:""}]转换成 [{key:value}]
-//                List<Map<String, String>> map = list.stream().map(e -> {
-//                    Map<String, String> result = new HashMap<>();
-//                    result.put(e.get("attributeKey").toString(), e.get("attributeValue").toString());
-//                    return result;
-//                }).collect(Collectors.toList());
-//                goodsImportItem.setProperties(JSONUtil.toJsonStr(map));
-//            }else{
-                goodsImportItem.setProperties("{\"保质期\":\"12个月\"}");
-//            }
+                if (StringUtils.isNotBlank(productAggregateMap.get(item.getProductId()).getDiyAttributesList())) {
+                    String diyAttributesList = productAggregateMap.get(item.getProductId()).getDiyAttributesList();
+                    List<Map> list = JSONUtil.toList(diyAttributesList, Map.class);
+                    //格式为{attributeKey:"",attributeValue:""}转换成 {key:value,key:value,key:value|:value}格式
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("{");
+                    for (int i = 0; i < list.size(); i++) {
+                        Map<String, String> e = list.get(i);
+                        String attributeKey = e.get("attributeKey");
+                        String attributeValue = e.get("attributeValue");
+
+                        // 处理 attributeValue 可能是逗号拼接的情况
+                        if (attributeValue != null && attributeValue.contains(",")) {
+                            // 如果是逗号拼接的值,保持原样或根据需求处理
+                            sb.append("\"").append(attributeKey).append("\":\"").append(attributeValue).append("\"");
+                        } else {
+                            sb.append("\"").append(attributeKey).append("\":\"").append(attributeValue).append("\"");
+                        }
+
+                        // 添加逗号分隔符(除了最后一个元素)
+                        if (i < list.size() - 1) {
+                            sb.append(",");
+                        }
+                    }
+                    sb.append("}");
+                    goodsImportItem.setProperties(sb.toString());
+                }else{
+                    goodsImportItem.setProperties("{\"颜色\":\"混色\"}");
+                }
 
                 //TODO 是否自营
                 goodsImportItem.setIsSelfOperated(1);
                 //税率
-                goodsImportItem.setTax( new BigDecimal("0.13"));
+                if(ObjectUtil.isNotEmpty(item.getTaxRate())){
+                    goodsImportItem.setTax( item.getTaxRate());
+                }else {
+                    goodsImportItem.setTax( new BigDecimal("0.13"));
+                }
+
+
                 //TODO 税收编码   默认填 1
-                goodsImportItem.setTaxCode("107022301");
+                if (ObjectUtil.isNotEmpty(item.getTaxCode())){
+                    goodsImportItem.setTaxCode(item.getTaxCode());
+                }else{
+                    goodsImportItem.setTaxCode("107022301");
+                }
                 batchGoods.add(goodsImportItem);
             });
             GoodsImportBo bo = new GoodsImportBo();
@@ -251,16 +279,18 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         GoodsImportBo bo =  new GoodsImportBo();
         bo.setAccount(username);
-        List<ExternalProductVo> externalProductVos = externalProductMapper.selectVoList(Wrappers.lambdaQuery(ExternalProduct.class).eq(ExternalProduct::getItemId, itemId));
-        Map<String, BigDecimal> decimalMap = externalProductVos.stream().collect(Collectors.toMap(ExternalProductVo::getProductNo, ExternalProductVo::getExternalPrice));
         bo.setGoods(products.stream().map(item ->{
+            ExternalProduct externalProduct = externalProductMap.get(item.getProductNo());
+            if (ObjectUtil.isEmpty(externalProduct)){
+                throw new ZhongcheException("商品不存在");
+            }
             GoodsImportItem goodsImportItem = new GoodsImportItem();
             goodsImportItem.setGoodsId(item.getProductNo());
             goodsImportItem.setDsPrice(item.getMarketPrice());
-            goodsImportItem.setPrice(decimalMap.get(item.getProductNo()));
+            goodsImportItem.setPrice(externalProduct.getExternalPrice());
             return goodsImportItem;
         }).toList());
         return tongJiPullController.egoodsPriceUpdate(bo);
@@ -280,7 +310,7 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products) {
+    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         try {
             GoodsImageUpdateBo bo = new GoodsImageUpdateBo();
             bo.setAccount(username);
@@ -305,13 +335,13 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap)  {
         try {
             GoodsPropertiesUpdateBo bo = new GoodsPropertiesUpdateBo();
             bo.setAccount(username);
             bo.setGoods(products.stream().map(item ->{
                 GoodsPropertiesUpdateItem goodsImageUpdateItem = new GoodsPropertiesUpdateItem();
-                goodsImageUpdateItem.setProperties("{\"保质期\":\"12个月\"}");
+                goodsImageUpdateItem.setProperties("{\"保质期\":\"13个月\"}");
                 goodsImageUpdateItem.setGoodsId(item.getProductNo());
                 return goodsImageUpdateItem;
             }).toList());
@@ -330,11 +360,16 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap,Map<Long, ExternalProductCategory> productCategoryMap)  {
         try {
             GoodsDetailBo bo = new GoodsDetailBo();
             bo.setAccount(username);
+
             bo.setGoods(products.stream().map(item ->{
+                ExternalProduct externalProduct = externalProductMap.get(item.getProductNo());
+                if (ObjectUtil.isEmpty(externalProduct)){
+                    throw new ZhongcheException("商品不存在");
+                }
                 GoodsDetailUpdateBo goodsImageUpdateItem = new GoodsDetailUpdateBo();
                 goodsImageUpdateItem.setBrandName(item.getBrandName());
                 goodsImageUpdateItem.setDescription(item.getPcDetail());
@@ -343,13 +378,12 @@ public class TongjiPushStrategy  implements ProductPushStrategy {
                 goodsImageUpdateItem.setIsSelfOperated(1);
                 goodsImageUpdateItem.setGoodsUrl("https://item.xiaoluwebsite.xyz/item?productNo="+item.getProductNo());
                 goodsImageUpdateItem.setThirdUrl(item.getReferenceLink());
-                goodsImageUpdateItem.setTaxCode("107022301");
-                goodsImageUpdateItem.setTax(BigDecimal.valueOf(0.13));
+                goodsImageUpdateItem.setTaxCode(externalProduct.getTaxCode());
                 goodsImageUpdateItem.setUnit(item.getUnitName());
-                goodsImageUpdateItem.setStandardCatalogId("1374013891398471680");
-                goodsImageUpdateItem.setStandardCatalogName("福利套餐");
+                ExternalProductCategory externalProductCategory = productCategoryMap.get(externalProduct.getExternalCategoryId());
+                goodsImageUpdateItem.setStandardCatalogId(externalProductCategory.getCategoryNo());
+                goodsImageUpdateItem.setStandardCatalogName(externalProductCategory.getCategoryName());
                 goodsImageUpdateItem.setGoodsId(item.getProductNo());
-                goodsImageUpdateItem.setTax(BigDecimal.valueOf(0.13));
                 return goodsImageUpdateItem;
             }).toList());
             return tongJiPullController.egoodsDetailUpdate(bo);

+ 7 - 6
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/YangGuangPushStrategy.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/YangGuangPushStrategy.java

@@ -1,4 +1,4 @@
-package org.dromara.external.handler.impl;
+package org.dromara.external.handler;
 
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -7,11 +7,12 @@ import org.dromara.external.api.zhongche.domain.vo.GoodsPriceUpdateVo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsStatusUpdateVo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
 import org.dromara.external.domain.ExternalProduct;
-import org.dromara.external.handler.ProductPushStrategy;
+import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.product.api.domain.ProductVo;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
+import java.util.Map;
 
 @Component("yangguangPushStrategy")
 @RequiredArgsConstructor
@@ -23,7 +24,7 @@ public class YangGuangPushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId, List<ProductVo> products) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId, List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         return null;
     }
 
@@ -33,17 +34,17 @@ public class YangGuangPushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId, List<ProductVo> products) {
+    public GoodsImageUpdateVo updateImages(Long itemId, List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId, List<ProductVo> products) {
+    public GoodsUpdateVo updateProperties(Long itemId, List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId, List<ProductVo> products) {
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap,Map<Long, ExternalProductCategory> productCategoryMap) {
         return null;
     }
 }

+ 19 - 16
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongChePushStrategy.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ZhongChePushStrategy.java

@@ -1,4 +1,4 @@
-package org.dromara.external.handler.impl;
+package org.dromara.external.handler;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -22,7 +22,6 @@ import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.domain.ExternalPushPoolLog;
 import org.dromara.external.domain.vo.ExternalProductVo;
-import org.dromara.external.handler.ProductPushStrategy;
 import org.dromara.external.mapper.ExternalProductMapper;
 import org.dromara.external.service.IExternalProductCategoryService;
 import org.dromara.external.service.IExternalPushPoolLogService;
@@ -30,9 +29,7 @@ import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.api.domain.zhongche.dto.ProductAggregateDto;
 import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.RestController;
 
 import java.math.BigDecimal;
 import java.util.*;
@@ -278,16 +275,19 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         GoodsImportBo bo =  new GoodsImportBo();
         bo.setAccount(username);
-        List<ExternalProductVo> externalProductVos = externalProductMapper.selectVoList(Wrappers.lambdaQuery(ExternalProduct.class).eq(ExternalProduct::getItemId, itemId));
-        Map<String, BigDecimal> decimalMap = externalProductVos.stream().collect(Collectors.toMap(ExternalProductVo::getProductNo, ExternalProductVo::getExternalPrice));
+
         bo.setGoods(products.stream().map(item ->{
+            ExternalProduct externalProduct = externalProductMap.get(item.getProductNo());
+            if (ObjectUtil.isEmpty(externalProduct)){
+                throw new ZhongcheException("商品不存在");
+            }
             GoodsImportItem goodsImportItem = new GoodsImportItem();
             goodsImportItem.setGoodsId(item.getProductNo());
             goodsImportItem.setDsPrice(item.getMarketPrice());
-            goodsImportItem.setPrice(decimalMap.get(item.getProductNo()));
+            goodsImportItem.setPrice(externalProduct.getExternalPrice());
             return goodsImportItem;
         }).toList());
         return zhongChePullController.egoodsPriceUpdate(bo);
@@ -307,7 +307,7 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products) {
+    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         try {
             GoodsImageUpdateBo bo = new GoodsImageUpdateBo();
             bo.setAccount(username);
@@ -332,7 +332,7 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap)  {
         try {
             GoodsPropertiesUpdateBo bo = new GoodsPropertiesUpdateBo();
             bo.setAccount(username);
@@ -357,11 +357,15 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap,Map<Long, ExternalProductCategory> productCategoryMap)  {
         try {
             GoodsDetailBo bo = new GoodsDetailBo();
             bo.setAccount(username);
             bo.setGoods(products.stream().map(item ->{
+                ExternalProduct externalProduct = externalProductMap.get(item.getProductNo());
+                if (ObjectUtil.isEmpty(externalProduct)){
+                    throw new ZhongcheException("商品不存在");
+                }
                 GoodsDetailUpdateBo goodsImageUpdateItem = new GoodsDetailUpdateBo();
                 goodsImageUpdateItem.setBrandName(item.getBrandName());
                 goodsImageUpdateItem.setDescription(item.getPcDetail());
@@ -370,13 +374,12 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
                 goodsImageUpdateItem.setIsSelfOperated(1);
                 goodsImageUpdateItem.setGoodsUrl("https://item.xiaoluwebsite.xyz/item?productNo="+item.getProductNo());
                 goodsImageUpdateItem.setThirdUrl(item.getReferenceLink());
-                goodsImageUpdateItem.setTaxCode("107022301");
-                goodsImageUpdateItem.setTax(BigDecimal.valueOf(0.13));
+                goodsImageUpdateItem.setTaxCode(externalProduct.getTaxCode());
                 goodsImageUpdateItem.setUnit(item.getUnitName());
-                goodsImageUpdateItem.setStandardCatalogId("1374013891398471680");
-                goodsImageUpdateItem.setStandardCatalogName("福利套餐");
+                ExternalProductCategory externalProductCategory = productCategoryMap.get(externalProduct.getExternalCategoryId());
+                goodsImageUpdateItem.setStandardCatalogId(externalProductCategory.getCategoryNo());
+                goodsImageUpdateItem.setStandardCatalogName(externalProductCategory.getCategoryName());
                 goodsImageUpdateItem.setGoodsId(item.getProductNo());
-                goodsImageUpdateItem.setTax(BigDecimal.valueOf(0.13));
                 return goodsImageUpdateItem;
             }).toList());
             return zhongChePullController.egoodsDetailUpdate(bo);

+ 7 - 7
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongZhiPushStrategy.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ZhongZhiPushStrategy.java

@@ -1,13 +1,13 @@
-package org.dromara.external.handler.impl;
+package org.dromara.external.handler;
 
-import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.domain.ExternalProduct;
-import org.dromara.external.handler.ProductPushStrategy;
+import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.product.api.domain.ProductVo;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
+import java.util.Map;
 
 @Component("ZF00030PushStrategy")
 public class ZhongZhiPushStrategy implements ProductPushStrategy {
@@ -22,7 +22,7 @@ public class ZhongZhiPushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         // TODO: 实现中职平台价格更新逻辑
         return null;
     }
@@ -34,19 +34,19 @@ public class ZhongZhiPushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products) {
+    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap) {
         // TODO: 实现中职平台图片更新逻辑
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap)  {
         // TODO: 实现中职平台规格更新逻辑
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products) {
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products, Map<String, ExternalProduct> externalProductMap,Map<Long, ExternalProductCategory> productCategoryMap)  {
         // TODO: 实现中职平台详情更新逻辑
         return null;
     }

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AccountActiveMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AccountActiveMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.json.JSONUtil;
@@ -10,7 +10,7 @@ import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsImportVo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.external.enums.MallMessageTypeEnum;

+ 15 - 3
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AfterSaleApplyMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleApplyMessageHandler.java

@@ -1,5 +1,6 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -10,8 +11,9 @@ import org.dromara.common.core.domain.zhongche.aftersale.domain.AfterSaleReason;
 import org.dromara.common.core.domain.zhongche.aftersale.vo.AfterSaleDetailVo;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
+import org.dromara.external.controller.tongji.TongJiPullController;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.dromara.product.api.domain.dto.OrderReturnDto;
@@ -31,6 +33,8 @@ public class AfterSaleApplyMessageHandler implements MallMessageHandler {
 
     private final ZhongChePullController zhongChePullController;
 
+    private final TongJiPullController tongJiPullController;
+
     private final RemoteExternalOrderService remoteExternalOrderService;
     @Override
     public MallMessageTypeEnum supportType() {
@@ -57,8 +61,16 @@ public class AfterSaleApplyMessageHandler implements MallMessageHandler {
         String afterSaleNo = (String) messageBo.getContent().get("afterSaleNo");
         AfterSaleDetailBo bo = new AfterSaleDetailBo();
         bo.setAfterSaleNo(afterSaleNo);
+        AfterSaleDetailVo afterSaleDetailVo = null;
         //查询售后单
-        AfterSaleDetailVo afterSaleDetailVo = zhongChePullController.mallAftersaleDetail(bo);
+        if("zhongche".equals(messageBo.getItemKey())){
+            afterSaleDetailVo = zhongChePullController.mallAftersaleDetail(bo);
+        }else if("tongji".equals(messageBo.getItemKey())){
+             afterSaleDetailVo = tongJiPullController.mallAftersaleDetail(bo);
+        }
+        if (ObjectUtil.isEmpty(afterSaleDetailVo)){
+            return new MessageVo("1","售后单不存在");
+        }
         OrderReturnDto orderReturnDto = remoteExternalOrderService.createReturnOrder(afterSaleDetailVo);
 
         if (orderReturnDto.getSuccess() == true){

+ 9 - 3
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AfterSaleCancelMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleCancelMessageHandler.java

@@ -1,11 +1,11 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.springframework.stereotype.Component;
@@ -30,7 +30,13 @@ public class AfterSaleCancelMessageHandler implements MallMessageHandler {
     @Override
     public MessageVo handle(MessageBo messageBo) {
         log.info("取消售后单:{}", JSONUtil.toJsonStr(messageBo));
-        return new MessageVo("1");
+        String afterSaleNo = (String) messageBo.getContent().get("afterSaleNo");
+        String cancelReason = (String) messageBo.getContent().get("cancelReason");
+        boolean b = remoteExternalOrderService.cancelReturnOrder(afterSaleNo, cancelReason);
+        if (b){
+            return new MessageVo("1");
+        }
+        return new MessageVo("0","取消订单失败");
     }
     /*@Override
     public MessageVo handle(MessageBo messageBo) {

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AfterSaleDeliverMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleDeliverMessageHandler.java

@@ -1,11 +1,11 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.dromara.product.api.domain.dto.OrderReturnDto;

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AfterSaleReceiveConfirmMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleReceiveConfirmMessageHandler.java

@@ -1,11 +1,11 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.dromara.product.api.domain.dto.OrderReturnDto;

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AfterSaleRefundNoticeMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/AfterSaleRefundNoticeMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -8,7 +8,7 @@ import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.springframework.stereotype.Component;

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillAbnormalPassMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillAbnormalPassMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillConfirmMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillConfirmMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillCreateMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillCreateMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillFinishMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillFinishMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillModifyMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillModifyMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillRejctPassMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillRejctPassMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

+ 2 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/BillRuleCreateMessageHandler.java → ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/BillRuleCreateMessageHandler.java

@@ -1,4 +1,4 @@
-package org.dromara.external.controller.zhongche.handle.impl;
+package org.dromara.external.handler.impl;
 
 import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
-import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
+import org.dromara.external.handler.MallMessageHandler;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä