소스 검색

中车API对接相关

Lijingyang 1 개월 전
부모
커밋
6278028b5f
34개의 변경된 파일1002개의 추가작업 그리고 17개의 파일을 삭제
  1. 12 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/RemoteZhongChePullService.java
  2. 2 1
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductService.java
  3. 2 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/OrderProductDto.java
  4. 15 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/ExternalProductController.java
  5. 4 4
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java
  6. 5 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductVo.java
  7. 26 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteZhongChePullServiceImpl.java
  8. 13 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java
  9. 26 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategyFactory.java
  10. 235 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongChePushStrategy.java
  11. 20 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongZhiPushStrategy.java
  12. 3 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalProductService.java
  13. 124 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductServiceImpl.java
  14. 7 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderProductController.java
  15. 5 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/zhongche/ZhongCheOrderMainController.java
  16. 171 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/zhongche/ZhongCheOrderReturnController.java
  17. 3 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderMainCrrcExt.java
  18. 5 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderProduct.java
  19. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderReturn.java
  20. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderReturnBo.java
  21. 3 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderMainVo.java
  22. 3 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderProductVo.java
  23. 8 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderReturnVo.java
  24. 8 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/dubbo/RemoteExternalOrderServiceImpl.java
  25. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java
  26. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderProductService.java
  27. 6 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderReturnService.java
  28. 28 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java
  29. 7 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderProductServiceImpl.java
  30. 135 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderReturnServiceImpl.java
  31. 47 5
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteProductServiceImpl.java
  32. 6 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/AddressAreaController.java
  33. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAddressAreaService.java
  34. 62 3
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AddressAreaServiceImpl.java

+ 12 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/RemoteZhongChePullService.java

@@ -1,5 +1,9 @@
 package org.dromara.external.api.zhongche;
 
+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.exception.api.ZhongcheException;
 import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
 import org.dromara.external.api.zhongche.domain.bo.OrderRejectBo;
@@ -15,4 +19,12 @@ public interface RemoteZhongChePullService {
     GoodsUpdateVo mallOrderConfirm(OrderConfirmBo bo) throws ZhongcheException;
     //拒单
     GoodsUpdateVo mallOrderReject( OrderRejectBo bo) throws ZhongcheException;
+    //售后接受
+    GoodsUpdateVo mallAftersaleConfirm( AfterSaleConfirmBo bo) throws ZhongcheException;
+    //售后拒绝
+    GoodsUpdateVo mallAftersaleReject(AfterSaleRejectBo bo) throws ZhongcheException;
+    //确认收到退货
+    GoodsUpdateVo mallAftersaleReturnGoodsReceived(AfterSaleReturnReceivedBo bo) throws ZhongcheException;
+    //确认退款
+    GoodsUpdateVo mallAftersaleRefund(AfterSaleRefundBo bo) throws ZhongcheException;
 }

+ 2 - 1
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductService.java

@@ -106,10 +106,11 @@ public interface RemoteProductService {
     boolean lockShoppingCart(Long productId, Long count,String accountName);
 
     //解定库存
-    boolean unlockShoppingCart(Long productId, String accountName);
     /**
      * 库存解定
      */
+    boolean unlockShoppingCart(Long productId, String accountName);
+
 
 
 }

+ 2 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/OrderProductDto.java

@@ -25,4 +25,6 @@ public class OrderProductDto implements Serializable {
     private String unit;
 
     private String barImgUrls;
+
+    private String brandName;
 }

+ 15 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/ExternalProductController.java

@@ -6,6 +6,8 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.external.handler.ProductPushStrategyFactory;
+import org.dromara.product.api.domain.ProductVo;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -37,6 +39,8 @@ public class ExternalProductController extends BaseController {
 
     private final IExternalProductService externalProductService;
 
+
+
     /**
      * 查询对外部推送商品列表
      */
@@ -130,6 +134,17 @@ public class ExternalProductController extends BaseController {
         return toAjax(externalProductService.shelfReview(bo));
     }
 
+    /**
+     * 批量新增对接商品
+     * @param itemId
+     * @param boList
+     * @return
+     */
+    @PostMapping("/batch/insert")
+    public R<Void> batchInsert(Long itemId,@RequestBody List<ProductVo> boList) {
+        return toAjax(externalProductService.saveExternalBatch(itemId,boList));
+    }
+
 
 
 

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

@@ -569,7 +569,7 @@ public class ZhongChePullController {
 
     //5.4.2	接受售后
     @PostMapping("/mall/aftersale/confirm")
-    public GoodsUpdateVo mallAftersaleConfirm(@RequestBody AfterSaleConfirmBo bo) {
+    public GoodsUpdateVo mallAftersaleConfirm(@RequestBody AfterSaleConfirmBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/confirm", bo);
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
         return zcr;
@@ -577,7 +577,7 @@ public class ZhongChePullController {
 
     //5.4.3	拒绝售后
     @PostMapping("/mall/aftersale/reject")
-    public GoodsUpdateVo mallAftersaleReject(@RequestBody AfterSaleRejectBo bo) {
+    public GoodsUpdateVo mallAftersaleReject(@RequestBody AfterSaleRejectBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/reject", bo);
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
         return zcr;
@@ -585,7 +585,7 @@ public class ZhongChePullController {
 
     //5.4.4	确认收到退货
     @PostMapping("/mall/aftersale/return/goods/received")
-    public GoodsUpdateVo mallAftersaleReturnGoodsReceived(@RequestBody AfterSaleReturnReceivedBo bo) {
+    public GoodsUpdateVo mallAftersaleReturnGoodsReceived(@RequestBody AfterSaleReturnReceivedBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/return/goods/received", bo);
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
         return zcr;
@@ -625,7 +625,7 @@ public class ZhongChePullController {
 
     //5.4.9	确认退款
     @PostMapping("/mall/aftersale/refund")
-    public GoodsUpdateVo mallAftersaleRefund(@RequestBody AfterSaleRefundBo bo) {
+    public GoodsUpdateVo mallAftersaleRefund(@RequestBody AfterSaleRefundBo bo) throws ZhongcheException{
         ZCR responseDto = doZcPost("/api/mall/aftersale/refund", bo);
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
         return zcr;

+ 5 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductVo.java

@@ -419,6 +419,11 @@ public class ExternalProductVo implements Serializable {
      */
     private String customizedCraft;
 
+    /**
+     * 第三方品类名称
+     */
+    private String externalCategoryName;
+
 
 
 }

+ 26 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteZhongChePullServiceImpl.java

@@ -3,6 +3,10 @@ package org.dromara.external.dubbo;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
+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.exception.api.ZhongcheException;
 import org.dromara.external.api.zhongche.RemoteZhongChePullService;
 import org.dromara.external.api.zhongche.domain.bo.OrderConfirmBo;
@@ -10,6 +14,7 @@ import org.dromara.external.api.zhongche.domain.bo.OrderRejectBo;
 import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
 import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.RequestBody;
 
 /**
  * author
@@ -33,4 +38,25 @@ public class RemoteZhongChePullServiceImpl implements RemoteZhongChePullService
         GoodsUpdateVo goodsUpdateVo = zhongChePullController.mallOrderReject(bo);
         return goodsUpdateVo;
     }
+
+    @Override
+    public GoodsUpdateVo mallAftersaleConfirm(AfterSaleConfirmBo bo) throws ZhongcheException {
+        GoodsUpdateVo goodsUpdateVo = zhongChePullController.mallAftersaleConfirm(bo);
+        return goodsUpdateVo;
+    }
+
+    @Override
+    public GoodsUpdateVo mallAftersaleReject(AfterSaleRejectBo bo) throws ZhongcheException {
+        return zhongChePullController.mallAftersaleReject(bo);
+    }
+
+    @Override
+    public GoodsUpdateVo mallAftersaleReturnGoodsReceived(AfterSaleReturnReceivedBo bo) throws ZhongcheException {
+        return zhongChePullController.mallAftersaleReturnGoodsReceived(bo);
+    }
+
+    @Override
+    public GoodsUpdateVo mallAftersaleRefund(AfterSaleRefundBo bo) throws ZhongcheException {
+        return zhongChePullController.mallAftersaleRefund(bo);
+    }
 }

+ 13 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java

@@ -0,0 +1,13 @@
+package org.dromara.external.handler;
+
+import org.dromara.external.domain.ExternalProduct;
+
+import java.util.List;
+
+public interface ProductPushStrategy {
+
+    /**
+     * 推送商品
+     */
+    void push(List<ExternalProduct> products);
+}

+ 26 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategyFactory.java

@@ -0,0 +1,26 @@
+package org.dromara.external.handler;
+
+import jakarta.annotation.Resource;
+import org.dromara.common.core.exception.api.ZhongcheException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component
+public class ProductPushStrategyFactory {
+
+    @Autowired
+    private Map<String, ProductPushStrategy> strategyMap;
+
+    public ProductPushStrategy getStrategy(String platformCode) {
+
+        ProductPushStrategy strategy = strategyMap.get(platformCode + "PushStrategy");
+
+        if (strategy == null) {
+            throw new ZhongcheException("未找到对应平台推送策略: " + platformCode);
+        }
+
+        return strategy;
+    }
+}

+ 235 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongChePushStrategy.java

@@ -0,0 +1,235 @@
+package org.dromara.external.handler.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.external.api.zhongche.domain.GoodsImportItem;
+import org.dromara.external.api.zhongche.domain.bo.GoodsImportBo;
+import org.dromara.external.api.zhongche.domain.vo.GoodsImportVo;
+import org.dromara.external.controller.zhongche.ZhongChePullController;
+import org.dromara.external.domain.ExternalProduct;
+import org.dromara.external.domain.ExternalProductCategory;
+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.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.util.*;
+import java.util.stream.Collectors;
+
+@Component("zhongchePushStrategy")
+@RequiredArgsConstructor
+public class ZhongChePushStrategy implements ProductPushStrategy {
+
+    @DubboReference
+    private final RemoteProductService remoteProductService;
+
+    private final ZhongChePullController zhongChePullController;
+
+    private final ExternalProductMapper externalProductMapper;
+
+    private final IExternalProductCategoryService externalProductCategoryService;
+
+    private final ObjectMapper objectMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void push(List<ExternalProduct> products) {
+        String username = "admin";
+        List<ExternalProductVo> productVoList = new ArrayList<>();
+        for (ExternalProduct product : products) {
+            ExternalProductVo vo = BeanUtil.toBean(product, ExternalProductVo.class);
+            productVoList.add(vo);
+        }
+        productVoList.forEach(item -> {
+            ExternalProductVo externalProductVo = BeanUtil.toBean(item, ExternalProductVo.class);
+            ProductVo productDetail = remoteProductService.getProductDetail(item.getProductId());
+            BeanUtil.copyProperties(productDetail, item);
+            item.setId(externalProductVo.getId());
+            item.setProductStatus(externalProductVo.getProductStatus());
+        });
+
+        // 收集所有 externalCategoryId
+        Set<Long> categoryIds = productVoList.stream()
+            .map(ExternalProductVo::getExternalCategoryId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+        if (!categoryIds.isEmpty()) {
+            List<ExternalProductCategory> categoryList =
+                externalProductCategoryService.listByIds(categoryIds);
+
+            // 转成 Map <id, name>
+            Map<Long, String> categoryMap = categoryList.stream()
+                .collect(Collectors.toMap(
+                    ExternalProductCategory::getId,
+                    ExternalProductCategory::getCategoryName
+                ));
+
+            // 回填分类名称
+            productVoList.forEach(item -> {
+                String categoryName =
+                    categoryMap.get(item.getExternalCategoryId());
+                item.setStandardCatalogName(categoryName);
+            });
+
+            List<Long> productIds = productVoList.stream()
+                .map(ExternalProductVo::getProductId)
+                .filter(Objects::nonNull) // 过滤空ID,避免远程调用报错
+                .collect(Collectors.toList());
+            //远程调用获取ProductAggregateDto列表
+            final Map<Long, ProductAggregateDto> productAggregateMap = new HashMap<>();
+
+            if (!CollectionUtils.isEmpty(productIds)) {
+                List<ProductAggregateDto> productAggregateList =
+                    remoteProductService.getProductInfo(productIds);
+
+                if (!CollectionUtils.isEmpty(productAggregateList)) {
+                    productAggregateMap.putAll(
+                        productAggregateList.stream()
+                            .collect(Collectors.toMap(
+                                ProductAggregateDto::getProductId,
+                                dto -> dto,
+                                (existing, replacement) -> existing
+                            ))
+                    );
+                }
+            }
+
+            List<GoodsImportItem> batchGoods = new ArrayList<>();
+        productVoList.forEach(item -> {
+            GoodsImportItem goodsImportItem = new GoodsImportItem();
+            goodsImportItem.setGoodsId(item.getProductId().toString());
+            goodsImportItem.setCatalogId(item.getBottomCategoryId().toString());
+            goodsImportItem.setCatalogName(item.getCategoryName());
+            goodsImportItem.setStandardCatalogId(item.getExternalCategoryId().toString());
+            goodsImportItem.setStandardCatalogName(item.getStandardCatalogName());
+            //这里有英文有中文混合,需要处理
+            String brandName = item.getBrandName();
+            if (isChinese(brandName)) {
+                goodsImportItem.setBrandName(brandName);
+            } else if (isEnglish(brandName)) {
+                goodsImportItem.setBrandNameEn(brandName);
+            }
+            goodsImportItem.setName(item.getItemName());
+            goodsImportItem.setDsPrice(item.getMarketPrice());
+            goodsImportItem.setPrice(item.getMemberPrice());
+            //第三方价格
+            goodsImportItem.setThirdPrice(item.getExternalPrice());
+            goodsImportItem.setUnit(item.getUnitName());
+            //TODO库存
+            goodsImportItem.setStock(productAggregateMap.get(item.getProductId()).getStock());
+            //图片
+            String rawImageStr = item.getProductImage();
+            List<String> imageList = new ArrayList<>();
+            if (StringUtils.isNotBlank(rawImageStr)) {
+                String[] imagePaths = rawImageStr.split(",");
+                for (String path : imagePaths) {
+                    String trimedPath = path.trim();
+                    if (StringUtils.isNotBlank(trimedPath)) {
+                        imageList.add(trimedPath);
+                    }
+                }
+            }
+            String barImgUrlsJson;
+            try {
+                barImgUrlsJson = objectMapper.writeValueAsString(imageList);
+            } catch (JsonProcessingException e) {
+                barImgUrlsJson = "[]";
+            }
+            goodsImportItem.setBarImgUrls(barImgUrlsJson);
+            //TODO商品描述
+            goodsImportItem.setDescription(productAggregateMap.get(item.getProductId()).getDescription());
+            //TODO商品规格  默认 颜色:白色
+            goodsImportItem.setProperties("{\"颜色\":\"白色\"}");
+            //TODO是否自营
+            goodsImportItem.setIsSelfOperated(item.getIsSelf());
+            //税率
+            goodsImportItem.setTax(item.getTaxRate());
+            //TODO税收编码   默认填1
+            goodsImportItem.setTaxCode("1");
+
+            batchGoods.add(goodsImportItem);
+        });
+            GoodsImportBo bo = new GoodsImportBo();
+            bo.setAccount(username);
+            bo.setGoods(batchGoods);
+            GoodsImportVo goodsImportVo = zhongChePullController.egoodsImport(bo);
+            if (goodsImportVo.getResult() == 1) {
+                externalProductMapper.update(
+                    Wrappers.lambdaUpdate(ExternalProduct.class)
+                        .set(ExternalProduct::getPushStatus, 1)
+                        .in(ExternalProduct::getId, productIds)
+                );
+            } else {
+                externalProductMapper.update(
+                    Wrappers.lambdaUpdate(ExternalProduct.class)
+                        .set(ExternalProduct::getPushStatus, 3)
+                        .set(ExternalProduct::getRemark, goodsImportVo.getMessage())
+                        .in(ExternalProduct::getId, productIds)
+                );
+            }
+        }
+    }
+
+    // --------------------- 核心判断方法 ---------------------
+    /**
+     * 判断字符串是否包含中文汉字(核心判断逻辑)
+     * @param str 待判断字符串
+     * @return true=包含中文,false=不包含
+     */
+    private boolean isChinese(String str) {
+        // 匹配任意中文字符(Unicode 中文编码范围)
+        return str.matches(".*[\\u4e00-\\u9fa5]+.*");
+    }
+
+    /**
+     * 判断字符串是否为纯英文(字母、数字、空格、常见标点)
+     * @param str 待判断字符串
+     * @return true=纯英文/数字,false=包含其他字符
+     */
+    private boolean isEnglish(String str) {
+        // 匹配字母、数字、空格、横线、点、下划线(可根据业务扩展)
+        return str.matches("[a-zA-Z0-9 \\-\\.\\_]+");
+    }
+
+    /*public static void main(String[] args) {
+        String username = "admin";
+        List<GoodsImportItem> batchGoods = new ArrayList<>();
+        GoodsImportItem item = new GoodsImportItem();
+        item.setGoodsId("362031");
+        item.setCatalogId("13012");
+        item.setCatalogName("原装墨盒");
+        item.setStandardCatalogId("1750717233748832257");
+        item.setStandardCatalogName("铁圈装订机耗材");
+        item.setBrandName("得力");
+        item.setName("得力");
+        item.setDsPrice(new BigDecimal(41));
+        item.setPrice(new BigDecimal(34));
+        item.setUnit("个");
+        item.setStock(100);
+        item.setBarImgUrls("[\"https://img1.com\",\"https://img2.com\"]");
+        item.setDescription("得力商品");
+        item.setProperties("{\"颜色\":\"红色\",\"尺寸\":\"XL\",\"材质\":\"棉|涤纶\"}");
+        item.setIsSelfOperated(1);
+        item.setTax(new BigDecimal(0.05));
+        item.setTaxCode("123456");
+        batchGoods.add(item);
+        GoodsImportBo bo = new GoodsImportBo();
+        bo.setAccount(username);
+        bo.setGoods(batchGoods);
+        ZhongChePullController zhongChePullController = new ZhongChePullController();
+        GoodsImportVo resp = zhongChePullController.egoodsImport(bo);
+        System.out.println(resp);
+    }*/
+}

+ 20 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongZhiPushStrategy.java

@@ -0,0 +1,20 @@
+package org.dromara.external.handler.impl;
+
+import org.dromara.external.domain.ExternalProduct;
+import org.dromara.external.handler.ProductPushStrategy;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component("ZF00030PushStrategy")
+public class ZhongZhiPushStrategy implements ProductPushStrategy {
+
+    @Override
+    public void push(List<ExternalProduct> products) {
+
+        for (ExternalProduct product : products) {
+            // 调用中职API
+            System.out.println("推送到中职平台: " + product.getId());
+        }
+    }
+}

+ 3 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalProductService.java

@@ -6,6 +6,7 @@ import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.external.domain.bo.ExternalProductBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.product.api.domain.ProductVo;
 
 import java.util.Collection;
 import java.util.List;
@@ -97,4 +98,6 @@ public interface IExternalProductService extends IService<ExternalProduct>{
      * 获取所有商品列表
      */
     List<ExternalProductVo> getAllProductList();
+
+    boolean saveExternalBatch(Long itemId,List<ProductVo> boList);
 }

+ 124 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -13,7 +14,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.external.domain.ExternalItem;
 import org.dromara.external.domain.ExternalProductCategory;
+import org.dromara.external.handler.ProductPushStrategy;
+import org.dromara.external.handler.ProductPushStrategyFactory;
+import org.dromara.external.service.IExternalItemService;
 import org.dromara.external.service.IExternalProductBrandService;
 import org.dromara.external.service.IExternalProductCategoryService;
 import org.dromara.product.api.RemoteProductService;
@@ -24,8 +29,10 @@ import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.mapper.ExternalProductMapper;
 import org.dromara.external.service.IExternalProductService;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -47,6 +54,10 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
     private final IExternalProductBrandService externalProductBrandService;
 
     private final IExternalProductCategoryService externalProductCategoryService;
+
+    private final IExternalItemService externalItemService;
+
+    private final ProductPushStrategyFactory strategyFactory;
     /**
      * 查询对外部推送商品
      *
@@ -166,6 +177,30 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
             item.setId(externalProductVo.getId());
             item.setProductStatus(externalProductVo.getProductStatus());
         });
+        // 收集所有 externalCategoryId
+        Set<Long> categoryIds = result.getRecords().stream()
+            .map(ExternalProductVo::getExternalCategoryId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+        if (!categoryIds.isEmpty()) {
+
+            List<ExternalProductCategory> categoryList =
+                externalProductCategoryService.listByIds(categoryIds);
+
+            // 转成 Map <id, name>
+            Map<Long, String> categoryMap = categoryList.stream()
+                .collect(Collectors.toMap(
+                    ExternalProductCategory::getId,
+                    ExternalProductCategory::getCategoryName
+                ));
+
+            // 回填分类名称
+            result.getRecords().forEach(item -> {
+                String categoryName =
+                    categoryMap.get(item.getExternalCategoryId());
+                item.setStandardCatalogName(categoryName);
+            });
+        }
         return TableDataInfo.build( result);
     }
 
@@ -176,10 +211,40 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
      * @return 推送成功数量
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public int batchPush(Long[] ids) {
-        List<ExternalProduct> externalProducts = baseMapper.selectList(new LambdaQueryWrapper<ExternalProduct>().eq(ExternalProduct::getPushStatus, 0).in(ExternalProduct::getId, ids));
-        if (CollUtil.isNotEmpty(externalProducts)) {
+        List<ExternalProduct> externalProducts = baseMapper.selectList(new LambdaQueryWrapper<ExternalProduct>()
+            .in(ExternalProduct::getId, ids));
+        if (CollUtil.isEmpty(externalProducts)) {
+            return 0;
         }
+        // ✅ 1️⃣ 校验第三方价格和分类
+        List<Long> invalidIds = externalProducts.stream()
+            .filter(p -> p.getExternalCategoryId() == null
+                || p.getExternalPrice() == null)
+            .map(ExternalProduct::getId)
+            .collect(Collectors.toList());
+
+        if (CollUtil.isNotEmpty(invalidIds)) {
+            throw new ServiceException("存在未设置第三方价格或品类的商品,请先完善后再推送");
+        }
+
+        // 2️⃣ 直接拿第一个的 itemId
+        Long itemId = externalProducts.get(0).getItemId();
+
+        // 3️⃣ 查询项目
+        ExternalItem item = externalItemService.getById(itemId);
+        if (item == null) {
+            return 0;
+        }
+
+        String itemKey = item.getItemKey();
+        // 4️⃣ 获取策略
+        ProductPushStrategy strategy =
+            strategyFactory.getStrategy(itemKey);
+
+        // 5️⃣ 执行推送
+        strategy.push(externalProducts);
         return baseMapper.update(Wrappers.lambdaUpdate(ExternalProduct.class)
             .set(ExternalProduct::getPushStatus, 1)
             .in(ExternalProduct::getId, ids));
@@ -258,4 +323,61 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
 
         return externalProductVos;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean saveExternalBatch(Long itemId, List<ProductVo> boList) {
+        if (boList == null || boList.isEmpty()) {
+            return false;
+        }
+
+        // 1️⃣ 收集 productId
+        Set<Long> productIds = boList.stream()
+            .map(ProductVo::getId)
+            .collect(Collectors.toSet());
+
+        // 2️⃣ 查询数据库已存在的数据
+        List<ExternalProduct> existList = lambdaQuery()
+            .eq(ExternalProduct::getItemId, itemId)
+            .in(ExternalProduct::getProductId, productIds)
+            .list();
+
+        // 转成 Map<productId, ExternalProduct>
+        Map<Long, ExternalProduct> existMap = existList.stream()
+            .collect(Collectors.toMap(
+                ExternalProduct::getProductId,
+                Function.identity()
+            ));
+
+        List<ExternalProduct> insertList = new ArrayList<>();
+        List<ExternalProduct> updateList = new ArrayList<>();
+
+        for (ProductVo vo : boList) {
+
+            ExternalProduct exist = existMap.get(vo.getId());
+
+            if (exist != null) {
+                // ====== 更新 ======
+                exist.setProductStatus(vo.getProductStatus());
+                updateList.add(exist);
+            } else {
+                // ====== 新增 ======
+                ExternalProduct externalProduct = new ExternalProduct();
+                externalProduct.setItemId(itemId);
+                externalProduct.setProductId(vo.getId());
+                externalProduct.setProductStatus(vo.getProductStatus());
+                insertList.add(externalProduct);
+            }
+        }
+
+        // 3️⃣ 批量执行
+        if (!insertList.isEmpty()) {
+            baseMapper.insertBatch(insertList);
+        }
+
+        if (!updateList.isEmpty()) {
+            baseMapper.updateBatchById(updateList);
+        }
+        return true;
+    }
 }

+ 7 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderProductController.java

@@ -45,6 +45,8 @@ public class OrderProductController extends BaseController {
         return orderProductService.queryPageList(bo, pageQuery);
     }
 
+
+
     /**
      * 导出订单商品明细列表
      */
@@ -66,6 +68,11 @@ public class OrderProductController extends BaseController {
         return R.ok(orderProductService.queryById(id));
     }
 
+    @GetMapping("/zhongche/{id}")
+    public R<List<OrderProductVo>> getInfos(@PathVariable("id") Long id) {
+        return R.ok(orderProductService.queryZhongCheById(id));
+    }
+
     /**
      * 新增订单商品明细
      */

+ 5 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/zhongche/ZhongCheOrderMainController.java

@@ -164,4 +164,9 @@ public class ZhongCheOrderMainController extends BaseController {
         return toAjax(zhongCheOrderMainService.setdeadline(id,repaymentDeadline));
     }
 
+    @PutMapping("/upload/invoice")
+    public R<Void> uploadInvoice(@RequestParam("id") Long id,@RequestParam("invoice") String invoice) {
+        return toAjax(zhongCheOrderMainService.uploadInvoice(id,invoice));
+    }
+
 }

+ 171 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/zhongche/ZhongCheOrderReturnController.java

@@ -2,13 +2,27 @@ package org.dromara.order.controller.zhongche;
 
 import java.util.List;
 
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+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.exception.api.ZhongcheException;
+import org.dromara.external.api.zhongche.RemoteZhongChePullService;
+import org.dromara.external.api.zhongche.domain.vo.GoodsUpdateVo;
+import org.dromara.order.domain.OrderReturn;
+import org.dromara.order.domain.OrderReturnCrrcExt;
+import org.dromara.order.domain.OrderReturnPickCrrc;
 import org.dromara.order.domain.bo.OrderReturnBo;
 import org.dromara.order.domain.vo.OrderReturnVo;
+import org.dromara.order.service.IOrderReturnCrrcExtService;
 import org.dromara.order.service.IOrderReturnService;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -37,6 +51,11 @@ public class ZhongCheOrderReturnController extends BaseController {
 
     private final IOrderReturnService zhongCheOrderReturnService;
 
+    private final RemoteZhongChePullService zhongChePullService;
+
+    private final IOrderReturnCrrcExtService orderReturnCrrcExtService;
+
+
     /**
      * 查询中车售后单列表
      */
@@ -66,7 +85,7 @@ public class ZhongCheOrderReturnController extends BaseController {
     @GetMapping("/{id}")
     public R<OrderReturnVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {
-        return R.ok(zhongCheOrderReturnService.queryById(id));
+        return R.ok(zhongCheOrderReturnService.queryZhongCheById(id));
     }
 
     /**
@@ -103,4 +122,155 @@ public class ZhongCheOrderReturnController extends BaseController {
                           @PathVariable("ids") Long[] ids) {
         return toAjax(zhongCheOrderReturnService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /**
+     * TODO接受售后 需要去看中车文档售后服务
+     * @param orderReturnPickCrrc
+     * @return
+     */
+    @PutMapping("/accept/aftersale")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Void> acceptAfterSale(OrderReturnPickCrrc orderReturnPickCrrc){
+        // 1. 空值校验:核心returnId不能为空
+        if (ObjectUtil.isEmpty(orderReturnPickCrrc.getReturnId())) {
+            return R.fail("退货单ID(returnId)不能为空");
+        }
+        boolean b = zhongCheOrderReturnService.updateOrderReturnPickCrrc(orderReturnPickCrrc);
+        boolean update = zhongCheOrderReturnService.lambdaUpdate()
+            .eq(OrderReturn::getId, orderReturnPickCrrc.getReturnId())
+            .set(OrderReturn::getStatus, 1)
+            .update();
+
+        if (b&&update){
+            //获取中车订单号和我们电商订单号
+            // 3. 核心新增:通过returnId查询关联的单号
+            Long returnId = orderReturnPickCrrc.getReturnId();
+            OrderReturn orderReturn = zhongCheOrderReturnService.getById(returnId);
+            String returnNo = orderReturn.getReturnNo(); // 退货单号
+
+            OrderReturnCrrcExt orderReturnCrrcExt = orderReturnCrrcExtService.lambdaQuery()
+                .eq(OrderReturnCrrcExt::getReturnId, returnId)
+                .one();
+            String crccAfterSaleNo = orderReturnCrrcExt.getCrccAfterSaleNo();
+
+            AfterSaleConfirmBo bo = new AfterSaleConfirmBo();
+            bo.setMallAfterSaleNo(returnNo);
+            bo.setAfterSaleNo(crccAfterSaleNo);
+            bo.setName(orderReturnPickCrrc.getName());
+            bo.setProvinceId(orderReturnPickCrrc.getProvinceId());
+            bo.setCityId(orderReturnPickCrrc.getCityId());
+            bo.setCountyId(orderReturnPickCrrc.getCountyId());
+            bo.setAddress(orderReturnPickCrrc.getAddress());
+            if (ObjectUtil.isNotEmpty(orderReturnPickCrrc.getZip())){
+                bo.setZip(orderReturnPickCrrc.getZip());
+            }
+            bo.setMobile(orderReturnPickCrrc.getMobile());
+            if (ObjectUtil.isNotEmpty(orderReturnPickCrrc.getPhone())){
+                bo.setPhone(orderReturnPickCrrc.getPhone());
+            }
+            bo.setEmail(orderReturnPickCrrc.getEmail());
+            GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallAftersaleConfirm(bo);
+            if (goodsUpdateVo.getResult() == 1){
+                return R.ok();
+            }else {
+                throw new ZhongcheException("售后单写入失败");
+            }
+        }
+        return R.fail("售后单地址写入失败");
+    }
+
+    /**
+     * TODO拒绝售后 需要去看中车文档售后服务
+     * @param id
+     * @param rejectReason
+     * @return
+     */
+    @PutMapping("/reject/aftersale")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Void> rejectAfterSale(Long id, String rejectReason){
+        OrderReturn orderReturn = zhongCheOrderReturnService.getById(id);
+        String returnNo = orderReturn.getReturnNo(); // 退货单号
+
+        OrderReturnCrrcExt orderReturnCrrcExt = orderReturnCrrcExtService.lambdaQuery()
+            .eq(OrderReturnCrrcExt::getReturnId, id)
+            .one();
+        String crccAfterSaleNo = orderReturnCrrcExt.getCrccAfterSaleNo();
+        //改状态
+        boolean update = zhongCheOrderReturnService.lambdaUpdate()
+            .eq(OrderReturn::getId, id)
+            .set(OrderReturn::getReturnStatus, 2)
+            .update();
+
+        AfterSaleRejectBo bo = new AfterSaleRejectBo();
+        bo.setAfterSaleNo(crccAfterSaleNo);
+        bo.setMallAfterSaleNo(returnNo);
+        bo.setRejectReason(rejectReason);
+        GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallAftersaleReject(bo);
+        if (goodsUpdateVo.getResult() == 1){
+            return R.ok();
+        }else {
+            throw new ZhongcheException("中车响应失败");
+        }
+    }
+
+    /**
+     * TODO确认收到退货 需要去看中车文档售后服务
+     * @param id
+     * @return
+     */
+    @PutMapping("/confirm/received")
+    @Transactional(rollbackFor = Exception.class)
+    public R<Void> confirmReceived(Long id){
+        boolean update = orderReturnCrrcExtService.lambdaUpdate()
+            .eq(OrderReturnCrrcExt::getReturnId, id)
+            .set(OrderReturnCrrcExt::getGoodsReturnStatus, 3)
+            .update();
+        if (update){
+            OrderReturnCrrcExt orderReturnCrrcExt = orderReturnCrrcExtService.lambdaQuery()
+                .eq(OrderReturnCrrcExt::getReturnId, id)
+                .one();
+            String crccAfterSaleNo = orderReturnCrrcExt.getCrccAfterSaleNo();
+            AfterSaleReturnReceivedBo bo = new AfterSaleReturnReceivedBo();
+            bo.setAfterSaleNo(crccAfterSaleNo);
+            GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallAftersaleReturnGoodsReceived(bo);
+            if (goodsUpdateVo.getResult() == 1){
+                return R.ok();
+            }else {
+                throw new ZhongcheException("中车响应失败");
+            }
+        }
+        return R.fail("退货状态更新失败");
+    }
+
+    /**
+     * TODO确认退款完成 需要去看中车文档售后服务
+     * @param id
+     * @return
+     */
+    @PutMapping("/refund/aftersale")
+    public R<Void> refundAfterSale(Long id){
+        boolean update = zhongCheOrderReturnService.lambdaUpdate()
+            .eq(OrderReturn::getId, id)
+            .set(OrderReturn::getReturnStatus, 3)
+            .update();
+        if (update){
+            OrderReturnCrrcExt orderReturnCrrcExt = orderReturnCrrcExtService.lambdaQuery()
+                .eq(OrderReturnCrrcExt::getReturnId, id)
+                .one();
+            String crccAfterSaleNo = orderReturnCrrcExt.getCrccAfterSaleNo();
+            AfterSaleRefundBo bo = new AfterSaleRefundBo();
+            bo.setAfterSaleNo(crccAfterSaleNo);
+            GoodsUpdateVo goodsUpdateVo = zhongChePullService.mallAftersaleRefund(bo);
+            if (goodsUpdateVo.getResult() == 1){
+                return R.ok();
+            }else {
+                throw new ZhongcheException("中车响应失败");
+            }
+        }
+        return R.fail("确认退款更新失败");
+    }
+
+
+
+
 }

+ 3 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderMainCrrcExt.java

@@ -202,6 +202,9 @@ public class OrderMainCrrcExt extends TenantEntity {
     //截止还款时间
     private Date repaymentDeadline;
 
+    //发票文件路径
+    private String invoiceAttachment;
+
 
 
 }

+ 5 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderProduct.java

@@ -195,5 +195,10 @@ public class OrderProduct extends TenantEntity {
 
     private String assignmentStatus;
 
+    /**
+     * 品牌名称
+     */
+    private String brandName;
+
 
 }

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderReturn.java

@@ -218,5 +218,7 @@ public class OrderReturn extends TenantEntity {
      */
     private String remark;
 
+    private String dataSource;
+
 
 }

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderReturnBo.java

@@ -211,6 +211,8 @@ public class OrderReturnBo extends BaseEntity {
      */
     private String remark;
 
+    private String dataSource;
+
     private List<OrderReturnItemBo> orderReturnItemList;
 
 

+ 3 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderMainVo.java

@@ -404,5 +404,8 @@ public class OrderMainVo implements Serializable {
     //截止还款时间
     private Date repaymentDeadline;
 
+    //包裹数量
+    private Long packageNum;
+
 
 }

+ 3 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderProductVo.java

@@ -236,5 +236,8 @@ public class OrderProductVo implements Serializable {
 
     private String dataSource;
 
+    //品牌名称
+    private String brandName;
+
 
 }

+ 8 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderReturnVo.java

@@ -260,8 +260,16 @@ public class OrderReturnVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    private String dataSource;
+
     private Date createTime;
 
     private List<OrderReturnItemVo> orderReturnItemList;
 
+    private String buyerName;
+
+    private String buyerMobile;
+
+    private String pickType;
+
 }

+ 8 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/dubbo/RemoteExternalOrderServiceImpl.java

@@ -37,6 +37,7 @@ import org.dromara.order.utils.kd100.domain.TrackData;
 import org.dromara.order.utils.kd100.domain.TrackVO;
 import org.dromara.product.api.RemoteExternalOrderService;
 import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.api.domain.dto.OrderNoDto;
 import org.dromara.product.api.domain.dto.OrderNoticeDto;
 import org.dromara.product.api.domain.dto.OrderPushDto;
@@ -542,6 +543,7 @@ public class RemoteExternalOrderServiceImpl implements RemoteExternalOrderServic
                 orderProduct.setProductUnitId(productDto.getProductUnitId());
                 orderProduct.setProductUnit(productDto.getUnit());
                 orderProduct.setProductImage(productDto.getBarImgUrls());
+                orderProduct.setBrandName(productDto.getBrandName());
             }
 
             int quantity = item.getNum()
@@ -609,6 +611,12 @@ public class RemoteExternalOrderServiceImpl implements RemoteExternalOrderServic
         //7、售后单状态
         orderReturn.setReturnStatus(convertAfterSaleStatus(afterSaleDetailVo.getAfterSaleStatus()));
 
+        //售后金额
+        ProductVo productDetail = remoteProductService.getProductDetail(Long.valueOf(afterSaleDetailVo.getAfterSaleGoods().getGoodsId()));
+        BigDecimal afterSaleAmount = productDetail.getMemberPrice().multiply(afterSaleDetailVo.getAfterSaleGoods().getNum());
+        afterSaleAmount = afterSaleAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
+
+        orderReturn.setAfterSaleAmount(afterSaleAmount);
         //设置商品总数量
         orderReturn.setReturnProductNum(afterSaleDetailVo.getAfterSaleGoods().getNum().longValue());
         //9、售后单创建时间

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java

@@ -122,4 +122,6 @@ public interface IOrderMainService extends IService<OrderMain> {
     boolean settlement(Long id);
 
     boolean setdeadline(Long id, Date deadline);
+
+    boolean uploadInvoice(Long id, String invoice);
 }

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderProductService.java

@@ -67,4 +67,6 @@ public interface IOrderProductService extends IService<OrderProduct>{
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    List<OrderProductVo> queryZhongCheById(Long id);
 }

+ 6 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderReturnService.java

@@ -1,7 +1,9 @@
 package org.dromara.order.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.validation.constraints.NotNull;
 import org.dromara.order.domain.OrderReturn;
+import org.dromara.order.domain.OrderReturnPickCrrc;
 import org.dromara.order.domain.vo.OrderReturnVo;
 import org.dromara.order.domain.bo.OrderReturnBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -75,4 +77,8 @@ public interface IOrderReturnService extends IService<OrderReturn>{
      * @return
      */
     TableDataInfo<OrderReturnVo> queryZhongchePageList(OrderReturnBo bo, PageQuery pageQuery);
+
+    OrderReturnVo queryZhongCheById(@NotNull(message = "主键不能为空") Long id);
+
+    boolean updateOrderReturnPickCrrc(OrderReturnPickCrrc orderReturnPickCrrc);
 }

+ 28 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.order.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -681,7 +682,6 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             List<Long> ids = records.stream()
                 .map(OrderMainVo::getId)
                 .collect(Collectors.toList());
-
             List<OrderMainCrrcExt> extList =
                 orderMainCrrcExtService.lambdaQuery()
                     .in(OrderMainCrrcExt::getId, ids)
@@ -694,6 +694,20 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
                         Function.identity()
                     ));
 
+            QueryWrapper<OrderDeliver> qw = new QueryWrapper<>();
+            qw.select("order_id", "COUNT(*) AS packageNum")
+                .in("order_id", ids)
+                .groupBy("order_id");
+
+            List<Map<String, Object>> packageList =
+                orderDeliverService.listMaps(qw);
+            Map<Long, Long> packageMap = CollUtil.isEmpty(packageList)
+                ? Collections.emptyMap()
+                : packageList.stream().collect(Collectors.toMap(
+                m -> ((Number) m.get("order_id")).longValue(),
+                m -> ((Number) m.get("packageNum")).longValue()
+            ));
+
             for (OrderMainVo vo : records) {
                 OrderMainCrrcExt ext = extMap.get(vo.getId());
                 if (ext != null) {
@@ -704,6 +718,10 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
                     vo.setInvoiceStatus(ext.getInvoiceStatus());
                     vo.setSettlementStatus(ext.getSettlementStatus());
                     vo.setRepaymentDeadline(ext.getRepaymentDeadline());
+                    // 包裹数
+                    vo.setPackageNum(
+                        packageMap.getOrDefault(vo.getId(), 0L)
+                    );
                 }
             }
         }
@@ -834,4 +852,13 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             .update();
         return update;
     }
+
+    @Override
+    public boolean uploadInvoice(Long id, String invoice) {
+        boolean update = orderMainCrrcExtService.lambdaUpdate()
+            .eq(OrderMainCrrcExt::getId, id)
+            .set(OrderMainCrrcExt::getInvoiceAttachment, invoice)
+            .update();
+        return update;
+    }
 }

+ 7 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderProductServiceImpl.java

@@ -4,6 +4,7 @@ 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.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -152,4 +153,10 @@ public class OrderProductServiceImpl extends ServiceImpl<OrderProductMapper, Ord
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    public List<OrderProductVo> queryZhongCheById(Long id) {
+        List<OrderProductVo> orderProductVos = baseMapper.selectVoList(new LambdaQueryWrapper<OrderProduct>().eq(OrderProduct::getOrderId, id));
+        return orderProductVos;
+    }
 }

+ 135 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderReturnServiceImpl.java

@@ -14,13 +14,18 @@ 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.customer.api.RemoteCustomerService;
+import org.dromara.order.domain.OrderMainCrrcExt;
 import org.dromara.order.domain.OrderReturn;
 import org.dromara.order.domain.OrderReturnItem;
+import org.dromara.order.domain.OrderReturnPickCrrc;
 import org.dromara.order.domain.bo.OrderReturnBo;
 import org.dromara.order.domain.bo.OrderReturnItemBo;
+import org.dromara.order.domain.vo.OrderMainCrrcExtVo;
 import org.dromara.order.domain.vo.OrderReturnVo;
 import org.dromara.order.mapper.OrderReturnItemMapper;
 import org.dromara.order.mapper.OrderReturnMapper;
+import org.dromara.order.service.IOrderMainCrrcExtService;
+import org.dromara.order.service.IOrderReturnPickCrrcService;
 import org.dromara.order.service.IOrderReturnService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -47,6 +52,10 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
 
     private final OrderReturnItemMapper orderReturnItemMapper;
 
+    private final IOrderMainCrrcExtService orderMainCrrcExtService;
+
+    private final IOrderReturnPickCrrcService orderReturnPickCrrcService;
+
     /**
      * 查询退货主
      *
@@ -61,6 +70,58 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
         return orderReturnVo;
     }
 
+    @Override
+    public OrderReturnVo queryZhongCheById(Long id) {
+        OrderReturnVo orderReturnVo = baseMapper.selectVoById(id);
+        orderReturnVo.setOrderReturnItemList(orderReturnItemMapper.selectVoList(new LambdaQueryWrapper<OrderReturnItem>()
+            .eq(OrderReturnItem::getReturnId, orderReturnVo.getId())));
+
+        // 3. 新增:关联查询OrderMainCrrcExt,补充buyerName和buyerMobile
+        Long orderId = orderReturnVo.getOrderId(); // 获取关联的订单主表ID
+        if (orderId != null) {
+            // 3.1 查询订单扩展表的买家信息
+            OrderMainCrrcExt ext = orderMainCrrcExtService.lambdaQuery()
+                .select(OrderMainCrrcExt::getBuyerName, OrderMainCrrcExt::getBuyerMobile)
+                .eq(OrderMainCrrcExt::getId, orderId)
+                .one(); // 单个查询,返回唯一结果
+
+            // 3.2 赋值买家信息到VO
+            if (ext != null) {
+                orderReturnVo.setBuyerName(ext.getBuyerName());
+                orderReturnVo.setBuyerMobile(ext.getBuyerMobile());
+            }
+        }
+        // ========== 新增:关联查询OrderReturnPickCrrc,补充pick_type ==========
+        Long returnId = orderReturnVo.getId(); // 取OrderReturn的主键ID(对应return_id)
+        if (returnId != null) {
+            // 查询pick表中对应return_id的pick_type
+            OrderReturnPickCrrc pickCrrc = orderReturnPickCrrcService.lambdaQuery()
+                .select(OrderReturnPickCrrc::getPickType) // 只查需要的字段
+                .eq(OrderReturnPickCrrc::getReturnId, returnId) // return_id关联OrderReturn的id
+                .one(); // 单个查询,返回唯一结果
+
+            // 赋值pick_type到VO
+            if (pickCrrc != null) {
+                orderReturnVo.setPickType(pickCrrc.getPickType()); // 需确保VO有setPickType方法
+            }
+        }
+
+        return orderReturnVo;
+    }
+
+    @Override
+    public boolean updateOrderReturnPickCrrc(OrderReturnPickCrrc orderReturnPickCrrc) {
+        if (orderReturnPickCrrc == null || orderReturnPickCrrc.getReturnId() == null) {
+            return false;
+        }
+        // 直接按 returnId 构造更新条件
+        LambdaQueryWrapper<OrderReturnPickCrrc> updateWrapper = new LambdaQueryWrapper<>();
+        updateWrapper.eq(OrderReturnPickCrrc::getReturnId, orderReturnPickCrrc.getReturnId());
+        // 移除主键(避免更新时主键冲突)
+        orderReturnPickCrrc.setId(null);
+        return orderReturnPickCrrcService.update(orderReturnPickCrrc, updateWrapper);
+    }
+
     /**
      * 分页查询退货主列表
      *
@@ -276,7 +337,81 @@ public class OrderReturnServiceImpl extends ServiceImpl<OrderReturnMapper, Order
     @Override
     public TableDataInfo<OrderReturnVo> queryZhongchePageList(OrderReturnBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<OrderReturn> lqw = buildQueryWrapper(bo);
+        lqw.eq(OrderReturn::getDataSource, "zhongche");
         Page<OrderReturnVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        List<OrderReturnVo> records = result.getRecords();
+        if (CollUtil.isNotEmpty( records)){
+            // 2. 提取所有orderId组成集合(去重,减少查询次数)
+            Set<Long> orderIdSet = records.stream()
+                .map(OrderReturnVo::getOrderId) // 假设orderId是Long类型,根据实际类型调整
+                .filter(Objects::nonNull) // 过滤空的orderId,避免无效查询
+                .collect(Collectors.toSet());
+
+            Map<Long, OrderMainCrrcExt> orderMainExtMap = new HashMap<>();
+            // 3. 如果有有效的orderId,才执行查询
+            if (CollUtil.isNotEmpty(orderIdSet)) {
+                // 3.1 批量查询orderMainCrrcExt数据(推荐批量查询,减少DB交互)
+                // 假设orderMainCrrcExtService有批量查询方法,key为id,返回Map<id, 包含buyer_name和buyer_mobile的对象>
+                //Map<Long, OrderMainCrrcExtVo> orderMainMap = orderMainCrrcExtService.getOrderMainMapByIds(orderIdSet);
+                orderMainExtMap = orderMainCrrcExtService.lambdaQuery()
+                    .in(OrderMainCrrcExt::getId, orderIdSet)
+                    .select(OrderMainCrrcExt::getId, OrderMainCrrcExt::getBuyerName, OrderMainCrrcExt::getBuyerMobile)
+                    .list()
+                    .stream()
+                    .collect(Collectors.toMap(
+                        OrderMainCrrcExt::getId,  // Map的key:订单ID
+                        item -> item,             // Map的value:整个OrderMainCrrcExt对象(包含buyerName和buyerMobile)
+                        (key1, key2) -> key2      // 重复key时的处理:保留后一个(根据业务选,也可以抛异常)
+                    ));
+            }
+
+            // ========== 第二步:新增处理orderReturnPickCrrc(核心新增) ==========
+            // 1. 提取OrderReturnVo的主键ID(return_id),关联OrderReturnPickCrrc表用
+            Set<Long> returnIdSet = records.stream()
+                .map(OrderReturnVo::getId) // 这里取的是OrderReturn的主键ID(对应return_id)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+            // 2. 初始化pick信息的Map,key=return_id,value=pick_type
+            Map<Long, String> returnPickTypeMap = new HashMap<>();
+            if (CollUtil.isNotEmpty(returnIdSet)) {
+                // 3. 批量查询OrderReturnPickCrrc,按return_id分组
+                returnPickTypeMap = orderReturnPickCrrcService.lambdaQuery()
+                    .in(OrderReturnPickCrrc::getReturnId, returnIdSet) // return_id关联OrderReturn的id
+                    .select(OrderReturnPickCrrc::getReturnId, OrderReturnPickCrrc::getPickType) // 只查需要的字段
+                    .list()
+                    .stream()
+                    .collect(Collectors.toMap(
+                        OrderReturnPickCrrc::getReturnId, // key=return_id(对应OrderReturn的id)
+                        OrderReturnPickCrrc::getPickType, // value=pick_type(直接取字段值)
+                        (key1, key2) -> key2 // 重复return_id时保留后一个,按业务调整
+                    ));
+            }
+
+
+            for (OrderReturnVo orderReturnVo : records) {
+                Long orderId = orderReturnVo.getId();
+                // 从Map中获取对应的扩展信息
+                OrderMainCrrcExt ext = orderMainExtMap.get(orderId);
+                if (ext != null) {
+                    String buyerName = ext.getBuyerName();    // 获取买家姓名
+                    String buyerMobile = ext.getBuyerMobile();// 获取买家手机号
+                    // 业务处理:比如赋值给订单对象、组装VO等
+                     orderReturnVo.setBuyerName(buyerName);
+                     orderReturnVo.setBuyerMobile(buyerMobile);
+                }
+
+                // 2. 赋值pick_type(新增逻辑)
+                Long returnId = orderReturnVo.getId(); // 取OrderReturn的主键ID
+                String pickType = returnPickTypeMap.get(returnId);
+                if (pickType != null) {
+                    orderReturnVo.setPickType(pickType); // 假设VO有setPickType方法,需确保字段存在
+                }
+            }
+
+            }
         return TableDataInfo.build(result);
     }
+
+
 }

+ 47 - 5
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteProductServiceImpl.java

@@ -14,6 +14,7 @@ import org.apache.commons.math3.stat.descriptive.summary.Product;
 import org.apache.dubbo.config.annotation.DubboService;
 import org.apache.seata.common.metadata.namingserver.Unit;
 import org.dromara.common.core.domain.zhongche.domain.Prices;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.ProductCategoryRemoteVo;
 import org.dromara.product.api.domain.ProductChangeLogApiVo;
@@ -347,7 +348,7 @@ public class RemoteProductServiceImpl implements RemoteProductService {
         // 1. 查商品基础表
         List<ProductBase> productList = productBaseService.list(new LambdaQueryWrapper<ProductBase>().in(ProductBase::getId, productIds));
         if (CollUtil.isEmpty(productList)) {
-            return Collections.emptyList();
+            throw new ServiceException("未查询到商品基础信息");
         }
         // 2. 查商品价格库存表
         List<ProductPriceInventory> priceInventoryList = productPriceInventoryService.list(new LambdaQueryWrapper<ProductPriceInventory>().in(ProductPriceInventory::getProductId, productIds));
@@ -446,12 +447,25 @@ public class RemoteProductServiceImpl implements RemoteProductService {
             ProductAggregateDto vo = new ProductAggregateDto();
             vo.setProductId(p.getId());
             vo.setName(p.getItemName());
-            vo.setDsPrice(priceInventoryMap.get(p.getId()).getMarketPrice());
-            vo.setPrice(priceInventoryMap.get(p.getId()).getMemberPrice());
-            vo.setStock(priceInventoryMap.get(p.getId()).getTotalInventory().intValue());
+            ProductPriceInventory priceInventory = priceInventoryMap.get(p.getId());
+            if (priceInventory.getMarketPrice() == null) {
+                throw new ServiceException("商品ID:" + p.getId() + " 未找到市场价格信息");
+            }
+            if (priceInventory.getMemberPrice() == null){
+                throw new ServiceException("商品ID:" + p.getId() + " 未找到会员价格信息");
+            }
+            if (priceInventory.getTotalInventory() == null){
+                throw new ServiceException("商品ID:" + p.getId() + " 未找到总库存信息");
+            }
+            vo.setDsPrice(priceInventory.getMarketPrice());
+            vo.setPrice(priceInventory.getMemberPrice());
+            vo.setStock(priceInventory.getTotalInventory().intValue());
             vo.setUnit(unitNameMap.get(p.getUnitId()));
             vo.setTax(priceInventoryMap.get(p.getId()).getTaxRate());
             ProductCategory category = categoryMap.get(p.getBottomCategoryId());
+            if (category == null) {
+                throw new ServiceException("商品ID:" + p.getId() + " 未配置");
+            }
             if (category != null) {
                 vo.setCategoryId(String.valueOf(category.getId()));
                 vo.setCategoryName(category.getCategoryName());
@@ -476,10 +490,13 @@ public class RemoteProductServiceImpl implements RemoteProductService {
 
             // 商品描述
             vo.setDescription(productDescMap.get(p.getId()));
-            vo.setTaxCode("123456");
+            vo.setTaxCode("1");
 
             // ===== 品牌名称规则处理 =====
             ProductBrand brand = finalBrandMap.get(p.getBrandId());
+            if (brand == null) {
+                throw new ServiceException("商品ID:" + p.getId() + " 未配置品牌");
+            }
             if (brand != null) {
                 if (StrUtil.isNotBlank(brand.getBrandName())) {
                     vo.setBrandName(brand.getBrandName());
@@ -531,7 +548,31 @@ public class RemoteProductServiceImpl implements RemoteProductService {
                 ));
         }
 
+        // 提取 brandId
+        List<Long> brandIds = productList.stream()
+            .map(ProductBase::getBrandId)
+            .filter(Objects::nonNull)
+            .distinct()
+            .toList();
+
+        //查询品牌名称
+        Map<Long, String> brandNameMap = Collections.emptyMap();
+        if (CollUtil.isNotEmpty(unitIds)) {
+            List<ProductBrand> brandNameList = productBrandService.list(
+                new LambdaQueryWrapper<ProductBrand>()
+                    .in(ProductBrand::getId, brandIds)
+            );
+
+            brandNameMap = brandNameList.stream()
+                .collect(Collectors.toMap(
+                    ProductBrand::getId,
+                    ProductBrand::getBrandName,
+                    (a,b)->a
+                ));
+        }
+
         Map<Long, String> finalUnitNameMap = unitNameMap;
+        Map<Long, String> finalBrandNameMap = brandNameMap;
 
         // ④ 组装订单商品DTO(快照)
         return productList.stream().map(p -> {
@@ -541,6 +582,7 @@ public class RemoteProductServiceImpl implements RemoteProductService {
             dto.setProductId(p.getId());
             dto.setProductNo(p.getProductNo());
             dto.setProductName(p.getItemName());
+            dto.setBrandName(finalBrandNameMap.get(p.getBrandId()));
 
             dto.setProductUnitId(p.getUnitId());
 

+ 6 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/AddressAreaController.java

@@ -52,6 +52,12 @@ public class AddressAreaController extends BaseController {
         return R.ok(addressAreaService.getChniaList(bo));
     }
 
+    @GetMapping("/getchina/area")
+    public R<List<AddressAreaVo>> getChinaArea(){
+        return R.ok(addressAreaService.getChinaArea());
+    }
+
+
     /**
      * 导出地区列表列表
      */

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAddressAreaService.java

@@ -69,4 +69,7 @@ public interface IAddressAreaService extends IService<AddressArea>{
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
     List<AddressAreaVo> getChniaList(AddressAreaBo bo);
+
+    List<AddressAreaVo> getChinaArea();
+
 }

+ 62 - 3
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AddressAreaServiceImpl.java

@@ -1,5 +1,7 @@
 package org.dromara.system.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -11,6 +13,7 @@ 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.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.dromara.system.domain.bo.AddressAreaBo;
 import org.dromara.system.domain.vo.AddressAreaVo;
@@ -18,9 +21,7 @@ import org.dromara.system.domain.AddressArea;
 import org.dromara.system.mapper.AddressAreaMapper;
 import org.dromara.system.service.IAddressAreaService;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -179,6 +180,64 @@ public class AddressAreaServiceImpl  extends ServiceImpl<AddressAreaMapper, Addr
         return provinceList;
     }
 
+    @Override
+    public List<AddressAreaVo> getChinaArea() {
+        // 1️⃣ 查询中国
+        AddressArea china = baseMapper.selectOne(
+            Wrappers.<AddressArea>lambdaQuery()
+                .eq(AddressArea::getLevel, 0)
+                .eq(AddressArea::getAreaName, "中国")
+                .eq(AddressArea::getStatus, "0")
+        );
+
+        if (china == null) {
+            return Collections.emptyList();
+        }
+
+        // 2️⃣ 查询中国下面所有省市区
+        List<AddressArea> allList = baseMapper.selectList(
+            Wrappers.<AddressArea>lambdaQuery()
+                .in(AddressArea::getLevel, 1, 2, 3)
+                .eq(AddressArea::getStatus, "0")
+        );
+
+        // 3️⃣ 转换成 VO
+        List<AddressAreaVo> voList = allList.stream().map(this::convertVo).collect(Collectors.toList());
+
+        // 4️⃣ 构建 id -> vo 映射
+        Map<Long, AddressAreaVo> map = voList.stream()
+            .collect(Collectors.toMap(AddressAreaVo::getId, v -> v));
+
+        // 5️⃣ 组装树
+        List<AddressAreaVo> provinceList = new ArrayList<>();
+
+        for (AddressAreaVo vo : voList) {
+
+            // 省级:parentCode = 中国id
+            if (vo.getParentCode().equals(china.getId())) {
+                provinceList.add(vo);
+                continue;
+            }
+
+            // 找父节点
+            AddressAreaVo parent = map.get(vo.getParentCode());
+            if (parent != null) {
+                if (parent.getChildren() == null) {
+                    parent.setChildren(new ArrayList<>());
+                }
+                parent.getChildren().add(vo);
+            }
+        }
+
+        return provinceList;
+    }
+
+    private AddressAreaVo convertVo(AddressArea area) {
+        AddressAreaVo vo = new AddressAreaVo();
+        BeanUtils.copyProperties(area, vo);
+        return vo;
+    }
+
 
     /**
      * 私有方法:构建省-市树形结构