Explorar el Código

中车API对接

Lijingyang hace 2 meses
padre
commit
95029411f1

+ 1 - 1
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/GoodsImportItem.java

@@ -87,7 +87,7 @@ public class GoodsImportItem {
      * 商品轮播图,JSON格式数组,其中第一张为主图
      * 商品轮播图,JSON格式数组,其中第一张为主图
      * 示例:["imgUrl1","imgUrl2"]
      * 示例:["imgUrl1","imgUrl2"]
      */
      */
-    private List<String> barImgUrls;
+    private String barImgUrls;
     /**
     /**
      * 商品介绍
      * 商品介绍
      */
      */

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

@@ -8,6 +8,7 @@ import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.api.domain.SiteProductRemoteBo;
 import org.dromara.product.api.domain.SiteProductRemoteBo;
 import org.dromara.product.api.domain.SiteProductRemoteResult;
 import org.dromara.product.api.domain.SiteProductRemoteResult;
 import org.dromara.product.api.domain.SiteProductRemoteVo;
 import org.dromara.product.api.domain.SiteProductRemoteVo;
+import org.dromara.product.api.domain.zhongche.dto.ProductAggregateDto;
 import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
 import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
 import org.dromara.product.api.domain.RemoteProductBrand;
 import org.dromara.product.api.domain.RemoteProductBrand;
 
 
@@ -80,4 +81,10 @@ public interface RemoteProductService {
      */
      */
     SiteProductRemoteResult querySiteProductPage(SiteProductRemoteBo bo);
     SiteProductRemoteResult querySiteProductPage(SiteProductRemoteBo bo);
 
 
+    /**
+     * zhongche获取商品信息
+     */
+    List<ProductAggregateDto> getProductInfo(List<Long> productIds);
+
+
 }
 }

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

@@ -0,0 +1,46 @@
+package org.dromara.product.api.domain.zhongche.dto;
+
+import lombok.Data;
+
+import javax.lang.model.element.NestingKind;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * author
+ * 时间:2026/2/4,13:38
+ */
+@Data
+public class ProductAggregateDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long productId;
+
+    private String BrandName;
+
+    private String BrandNameEn;
+
+    private String productName;
+
+    private String name;
+
+    private BigDecimal dsPrice;
+
+    private BigDecimal price;
+
+    private String unit;
+
+    private Integer stock;
+
+    private String barImgUrls;
+
+    private String description;
+
+    private String properties;
+
+    private Integer isSelfOperated;
+
+    private BigDecimal tax;
+
+    private String taxCode;
+}

+ 6 - 7
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java

@@ -613,18 +613,17 @@ public class ZhongChePushController {
         }
         }
 
 
         // 5. 按消息类型处理业务
         // 5. 按消息类型处理业务
+        MessageVo messageVo;
         try {
         try {
-            mallMessageDispatcher.dispatch(messageBo);
+            messageVo = mallMessageDispatcher.dispatch(messageBo);
         } catch (Exception e) {
         } catch (Exception e) {
             log.error("消息处理异常,messageId={}", messageBo.getId(), e);
             log.error("消息处理异常,messageId={}", messageBo.getId(), e);
             return ZCR.fail("5007", "消息处理失败");
             return ZCR.fail("5007", "消息处理失败");
         }
         }
-
-
-        // 6. 构造响应业务参数
-        MessageVo messageVo = new MessageVo();
-        messageVo.setResult("1");
-        messageVo.setMessage("success");
+        // 防御式兜底
+        if (messageVo == null) {
+            messageVo = new MessageVo("0", "消息处理无返回结果");
+        }
 
 
         String respBizJson = JSONUtil.toJsonStr(messageVo);
         String respBizJson = JSONUtil.toJsonStr(messageVo);
         String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);
         String respDataBase64 = Base64.encode(respBizJson, StandardCharsets.UTF_8);

+ 5 - 4
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/MallMessageDispatcher.java

@@ -2,6 +2,7 @@ package org.dromara.external.controller.zhongche.handle;
 
 
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
 import org.dromara.external.api.zhongche.domain.bo.MessageBo;
+import org.dromara.external.api.zhongche.domain.vo.MessageVo;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
@@ -21,19 +22,19 @@ public class MallMessageDispatcher {
         }
         }
     }
     }
 
 
-    public void dispatch(MessageBo messageBo) {
+    public MessageVo dispatch(MessageBo messageBo) {
         MallMessageTypeEnum type = MallMessageTypeEnum.of(messageBo.getType());
         MallMessageTypeEnum type = MallMessageTypeEnum.of(messageBo.getType());
         if (type == null) {
         if (type == null) {
             log.warn("未知消息类型:{}", messageBo.getType());
             log.warn("未知消息类型:{}", messageBo.getType());
-            return;
+            return new MessageVo("0", "未知消息类型");
         }
         }
 
 
         MallMessageHandler handler = handlerMap.get(type);
         MallMessageHandler handler = handlerMap.get(type);
         if (handler == null) {
         if (handler == null) {
             log.warn("未找到消息处理器,type={}", type);
             log.warn("未找到消息处理器,type={}", type);
-            return;
+            return new MessageVo("0", "未找到消息处理器");
         }
         }
 
 
-        handler.handle(messageBo);
+        return handler.handle(messageBo);
     }
     }
 }
 }

+ 85 - 18
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/handle/impl/AccountActiveMessageHandler.java

@@ -15,10 +15,14 @@ import org.dromara.external.controller.zhongche.handle.MallMessageHandler;
 import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.external.domain.vo.ExternalProductVo;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.external.enums.MallMessageTypeEnum;
 import org.dromara.external.service.IExternalProductService;
 import org.dromara.external.service.IExternalProductService;
+import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.zhongche.dto.ProductAggregateDto;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * author
  * author
@@ -33,6 +37,9 @@ public class AccountActiveMessageHandler implements MallMessageHandler {
 
 
     private final IExternalProductService externalProductService;
     private final IExternalProductService externalProductService;
 
 
+    private final RemoteProductService remoteProductService;
+
+
     @Override
     @Override
     public MallMessageTypeEnum supportType() {
     public MallMessageTypeEnum supportType() {
         return MallMessageTypeEnum.ACCOUNT_ACTIVE;
         return MallMessageTypeEnum.ACCOUNT_ACTIVE;
@@ -47,30 +54,90 @@ public class AccountActiveMessageHandler implements MallMessageHandler {
             log.info("商品导入:无可导入商品,username={}", username);
             log.info("商品导入:无可导入商品,username={}", username);
             return new MessageVo("0","无可导入商品");
             return new MessageVo("0","无可导入商品");
         }
         }
-        int size = allProductList.size();
-        for (int i = 0; i < size; i += 50) {
-            int end = Math.min(i + 50, size);
-            List<ExternalProductVo> batchList = allProductList.subList(i, end);
-            ExternalProductVo externalProductVo = batchList.get(0);
-            GoodsImportItem goodsImportItem = new GoodsImportItem();
-            goodsImportItem.setGoodsId(externalProductVo.getProductId().toString());
-            goodsImportItem.setCatalogId(externalProductVo.getExternalCategoryId().toString());
-            goodsImportItem.setCatalogName(externalProductVo.getItemName());
 
 
+        List<Long> productIds = allProductList.stream()
+                .map(ExternalProductVo::getProductId)
+                .toList();
 
 
-            //GoodsImportBo goodsImportBo = new GoodsImportBo(username, batchList);
-            //GoodsImportVo result = zhongChePullController.egoodsImport(goodsImportBo);
-        }
+        List<ProductAggregateDto> productInfo = remoteProductService.getProductInfo(productIds);
+
+
+        Map<Long, ExternalProductVo> externalMap = allProductList.stream()
+                .collect(Collectors.toMap(
+                        ExternalProductVo::getProductId,
+                        Function.identity(),
+                        (a, b) -> a
+                ));
+
+        List<GoodsImportItem> goodsList = productInfo.stream().map(p -> {
+            GoodsImportItem item = new GoodsImportItem();
+
+            ExternalProductVo ext = externalMap.get(p.getProductId());
+
+            // ===== 商品唯一标识 =====
+            item.setGoodsId(p.getProductId().toString());
 
 
-        //GoodsImportBo goodsImportBo = new GoodsImportBo(username, allProductList);
+            // ===== 品目(只能来自 ExternalProductVo)=====
+            item.setCatalogId(ext.getCategoryId().toString());
+            item.setCatalogName(ext.getCategoryName());
+            item.setStandardCatalogId(ext.getExternalCategoryId().toString());
+            item.setStandardCatalogName(ext.getStandardCatalogName());
 
 
-        //zhongChePullController.egoodsImport()
+            // ===== 商品基础 =====
+            item.setName(p.getName());
+            item.setUnit(p.getUnit());
+            item.setStock(p.getStock());
 
 
+            // ===== 价格 =====
+            item.setDsPrice(p.getDsPrice());
+            item.setPrice(p.getPrice());
 
 
+            // ===== 税 =====
+            item.setTax(p.getTax());
+            item.setTaxCode(p.getTaxCode());
 
 
-        /*if (!= null){
-            return new MessageVo("1");
-        }*/
-        return new MessageVo("0","取消订单失败");
+            // ===== 品牌 =====
+            if (p.getBrandName() != null){
+                item.setBrandName(p.getBrandName());
+            }else {
+                item.setBrandNameEn(p.getBrandNameEn());
+            }
+
+            // ===== 图片 / 描述 / 规格 =====
+            item.setBarImgUrls(p.getBarImgUrls());
+            item.setDescription(p.getDescription());
+            item.setProperties(p.getProperties());
+
+            // ===== 自营 =====
+            item.setIsSelfOperated(p.getIsSelfOperated());
+
+            return item;
+        }).toList();
+
+        int size = goodsList.size();
+
+        for (int i = 0; i < size; i += 50) {
+            int end = Math.min(i + 50, size);
+            List<GoodsImportItem> batchGoods = goodsList.subList(i, end);
+
+            GoodsImportBo bo = new GoodsImportBo();
+            bo.setAccount(username);
+            bo.setGoods(batchGoods);
+            GoodsImportVo resp = zhongChePullController.egoodsImport(bo);
+            // ===== 结果校验 =====
+            if (resp == null) {
+                log.error("商品导入失败,batch={}~{},中车无响应", i, end);
+                return new MessageVo("0", "商品导入失败:中车无响应");
+            }
+
+            if (resp.getResult() == 0) {
+                log.error("商品导入失败,batch={}~{},原因={}",
+                        i, end,
+                        resp.getMessage()
+                );
+                return new MessageVo("0", "商品导入失败:" + resp.getMessage());
+            }
+        }
+        return new MessageVo("1","商品导入成功");
     }
     }
 }
 }

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

@@ -0,0 +1,121 @@
+package org.dromara.external.controller.zhongche.handle.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.external.api.zhongche.domain.bo.MessageBo;
+import org.dromara.external.api.zhongche.domain.invoice.bo.InvoiceApplyDetailBo;
+import org.dromara.external.api.zhongche.domain.invoice.bo.InvoiceApplyOrdersBo;
+import org.dromara.external.api.zhongche.domain.invoice.domain.InvoiceOrder;
+import org.dromara.external.api.zhongche.domain.invoice.vo.InvoiceApplyDetailVo;
+import org.dromara.external.api.zhongche.domain.invoice.vo.InvoiceApplyOrdersVo;
+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.enums.MallMessageTypeEnum;
+import org.dromara.product.api.RemoteExternalOrderService;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * author
+ * 时间:2026/2/4,15:17
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class InvoiceApplyMessageHandler implements MallMessageHandler {
+
+    private final ZhongChePullController zhongChePullController;
+
+    private final RemoteExternalOrderService remoteExternalOrderService;
+    @Override
+    public MallMessageTypeEnum supportType() {
+        return MallMessageTypeEnum.INVOICE_APPLY;
+    }
+
+    @Override
+    public MessageVo handle(MessageBo messageBo) {
+        Map<String, Object> content = (Map<String, Object>) messageBo.getContent();
+        String applyNo = String.valueOf(content.get("applyNo"));
+
+        if (StrUtil.isBlank(applyNo)) {
+            return new MessageVo("0", "缺少开票申请编号");
+        }
+        try {
+            // 1、查询开票申请详情
+            InvoiceApplyDetailBo bo = new InvoiceApplyDetailBo(applyNo);
+            bo.setApplyNo(applyNo);
+            InvoiceApplyDetailVo invoiceApplyDetailVo = zhongChePullController.mallInvoiceApplyDetail(bo);
+
+            if (invoiceApplyDetailVo == null) {
+                return new MessageVo("0", "未查询到开票申请详情");
+            }
+
+            //TODO解析TOKEN 获取电商账号
+            //先假设一个电商账号 123456
+            // 2️、 查询开票申请订单列表(分页)
+            String account = "123456";
+            List<InvoiceOrder> invoiceOrders = queryAllInvoiceOrders(account, applyNo);
+
+            if (CollUtil.isEmpty(invoiceOrders)) {
+                return new MessageVo("0", "开票申请无订单数据");
+            }
+
+            // 3、 和本地数据核对
+            //boolean checkResult = remoteExternalOrderService.checkInvoiceData(invoiceApplyDetailVo, invoiceOrders);
+
+            /*if (!checkResult) {
+                return new MessageVo("0", "开票数据校验不通过");
+            }*/
+
+            // 4、更新本地开票申请状态
+            //invoiceService.saveOrUpdateInvoice(invoiceApplyDetailVo, invoiceOrders);
+
+            return new MessageVo("1", "开票申请处理成功");
+
+        } catch (Exception e) {
+            log.error("处理开票申请消息失败,applyNo={}", applyNo, e);
+            return new MessageVo("0", "系统异常");
+        }
+
+    }
+
+    private List<InvoiceOrder> queryAllInvoiceOrders(String account, String applyNo) {
+
+        List<InvoiceOrder> result = new ArrayList<>();
+
+        int current = 1;
+        int size = 50; // 文档最大 50
+
+        while (true) {
+            InvoiceApplyOrdersBo bo = new InvoiceApplyOrdersBo();
+            bo.setCurrent(current);
+            bo.setSize(size);
+            bo.setAccount(account);
+            bo.setApplyNo(applyNo);
+
+            InvoiceApplyOrdersVo resp =
+                zhongChePullController.mallInvoiceApplyOrders(bo);
+
+            if (resp == null || CollUtil.isEmpty(resp.getInvoiceOrders())) {
+                break;
+            }
+
+            result.addAll(resp.getInvoiceOrders());
+
+            // 已经到最后一页
+            if (current >= resp.getPages()) {
+                break;
+            }
+            current++;
+        }
+
+        return result;
+    }
+}

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

@@ -53,12 +53,22 @@ public class ExternalProductVo implements Serializable {
     @ExcelProperty(value = "分类id")
     @ExcelProperty(value = "分类id")
     private Long categoryId;
     private Long categoryId;
 
 
+    /**
+     * 电商品目名称
+     */
+    private String catalogName;
+
     /**
     /**
      * 外部分类id
      * 外部分类id
      */
      */
     @ExcelProperty(value = "外部分类id")
     @ExcelProperty(value = "外部分类id")
     private Long externalCategoryId;
     private Long externalCategoryId;
 
 
+    /**
+     * 第三方品目名称
+     */
+    private String standardCatalogName;
+
     /**
     /**
      * 推送状态 0未推送,1已推送
      * 推送状态 0未推送,1已推送
      */
      */

+ 62 - 3
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductServiceImpl.java

@@ -13,6 +13,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.external.domain.ExternalProductCategory;
+import org.dromara.external.service.IExternalProductBrandService;
+import org.dromara.external.service.IExternalProductCategoryService;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.api.domain.ProductVo;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -22,9 +25,8 @@ import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.mapper.ExternalProductMapper;
 import org.dromara.external.mapper.ExternalProductMapper;
 import org.dromara.external.service.IExternalProductService;
 import org.dromara.external.service.IExternalProductService;
 
 
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
+import java.util.*;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * 对外部推送商品Service业务层处理
  * 对外部推送商品Service业务层处理
@@ -42,6 +44,9 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
     @DubboReference
     @DubboReference
     private RemoteProductService remoteProductService;
     private RemoteProductService remoteProductService;
 
 
+    private final IExternalProductBrandService externalProductBrandService;
+
+    private final IExternalProductCategoryService externalProductCategoryService;
     /**
     /**
      * 查询对外部推送商品
      * 查询对外部推送商品
      *
      *
@@ -197,6 +202,60 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
     @Override
     @Override
     public List<ExternalProductVo> getAllProductList() {
     public List<ExternalProductVo> getAllProductList() {
         List<ExternalProductVo> externalProductVos = baseMapper.selectVoList();
         List<ExternalProductVo> externalProductVos = baseMapper.selectVoList();
+        if (CollUtil.isEmpty(externalProductVos)) {
+            return externalProductVos;
+        }
+        // 2. 收集所有分类 id(两个字段一起)
+        Set<Long> categoryIds = new HashSet<>();
+        for (ExternalProductVo vo : externalProductVos) {
+            if (vo.getCategoryId() != null) {
+                categoryIds.add(vo.getCategoryId());
+            }
+            if (vo.getExternalCategoryId() != null) {
+                categoryIds.add(vo.getExternalCategoryId());
+            }
+        }
+
+        if (CollUtil.isEmpty(categoryIds)) {
+            return externalProductVos;
+        }
+
+        // 3. 一次性查询分类表
+        List<ExternalProductCategory> categoryList =
+            externalProductCategoryService.lambdaQuery()
+                .in(ExternalProductCategory::getProductCategoryId, categoryIds)
+                .list();
+
+        // 4. 转 Map:id -> 分类名称
+        Map<Long, String> categoryNameMap =
+            categoryList.stream()
+                .collect(Collectors.toMap(
+                    ExternalProductCategory::getProductCategoryId,
+                    ExternalProductCategory::getCategoryName,
+                    (a, b) -> a
+                ));
+
+        // 5. 回填分类名称
+        for (ExternalProductVo vo : externalProductVos) {
+
+            // 电商品目名称
+            if (vo.getCategoryId() != null) {
+                vo.setCatalogName(categoryNameMap.get(vo.getCategoryId()));
+            }
+
+            // 第三方品目名称
+            if (vo.getExternalCategoryId() != null) {
+                vo.setStandardCatalogName(categoryNameMap.get(vo.getExternalCategoryId()));
+            }
+        }
+
+        //查询所有商品信息
+        List<Long> productIds = externalProductVos.stream()
+            .map(ExternalProductVo::getProductId)
+            .toList();
+
+
+
         return externalProductVos;
         return externalProductVos;
     }
     }
 }
 }

+ 1 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductBase.java

@@ -62,7 +62,7 @@ public class ProductBase extends TenantEntity {
     /**
     /**
      * 单位id
      * 单位id
      */
      */
-    private String unitId;
+    private Long unitId;
 
 
     /**
     /**
      * 产品图片URL
      * 产品图片URL

+ 145 - 3
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteProductServiceImpl.java

@@ -1,13 +1,18 @@
 package org.dromara.product.dubbo;
 package org.dromara.product.dubbo;
 
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.math3.stat.descriptive.summary.Product;
 import org.apache.dubbo.config.annotation.DubboService;
 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.domain.zhongche.domain.Prices;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.ProductCategoryRemoteVo;
 import org.dromara.product.api.domain.ProductCategoryRemoteVo;
@@ -16,17 +21,16 @@ import org.dromara.product.api.domain.ProductVo;
 import org.dromara.product.api.domain.SiteProductRemoteBo;
 import org.dromara.product.api.domain.SiteProductRemoteBo;
 import org.dromara.product.api.domain.SiteProductRemoteResult;
 import org.dromara.product.api.domain.SiteProductRemoteResult;
 import org.dromara.product.api.domain.SiteProductRemoteVo;
 import org.dromara.product.api.domain.SiteProductRemoteVo;
+import org.dromara.product.api.domain.zhongche.dto.ProductAggregateDto;
 import org.dromara.product.api.domain.zhongche.dto.StocksResult;
 import org.dromara.product.api.domain.zhongche.dto.StocksResult;
 import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
 import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
-import org.dromara.product.domain.ProductWarehouseInventory;
+import org.dromara.product.domain.*;
 import org.dromara.product.domain.bo.SiteProductBo;
 import org.dromara.product.domain.bo.SiteProductBo;
 import org.dromara.product.domain.vo.*;
 import org.dromara.product.domain.vo.*;
-import org.dromara.product.domain.ProductPriceInventory;
 import org.dromara.product.domain.bo.ProductCategoryBo;
 import org.dromara.product.domain.bo.ProductCategoryBo;
 import org.dromara.product.api.domain.RemoteProductBrand;
 import org.dromara.product.api.domain.RemoteProductBrand;
-import org.dromara.product.domain.ProductBrand;
 import org.dromara.product.domain.bo.ProductBaseBo;
 import org.dromara.product.domain.bo.ProductBaseBo;
 import org.dromara.product.domain.bo.ProductChangeLogBo;
 import org.dromara.product.domain.bo.ProductChangeLogBo;
 import org.dromara.product.service.*;
 import org.dromara.product.service.*;
@@ -35,6 +39,7 @@ import org.springframework.stereotype.Service;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -60,6 +65,12 @@ public class RemoteProductServiceImpl implements RemoteProductService {
 
 
     private final IProductWarehouseInventoryService productWarehouseInventoryService;
     private final IProductWarehouseInventoryService productWarehouseInventoryService;
 
 
+    private final IProductUnitService productUnitService;
+
+    private final IProductExtendService productExtendService;
+
+    private final IProductClassificationService productClassificationService;
+
     /**
     /**
      * 获取商品详情
      * 获取商品详情
      *
      *
@@ -316,5 +327,136 @@ public class RemoteProductServiceImpl implements RemoteProductService {
         return result;
         return result;
     }
     }
 
 
+    @Override
+    public List<ProductAggregateDto> getProductInfo(List<Long> productIds) {
+        if (CollUtil.isEmpty(productIds)) {
+            return Collections.emptyList();
+        }
+        // 1. 查商品基础表
+        List<ProductBase> productList = productBaseService.list(new LambdaQueryWrapper<ProductBase>().in(ProductBase::getId, productIds));
+        if (CollUtil.isEmpty(productList)) {
+            return Collections.emptyList();
+        }
+        // 2. 查商品价格库存表
+        List<ProductPriceInventory> priceInventoryList = productPriceInventoryService.list(new LambdaQueryWrapper<ProductPriceInventory>().in(ProductPriceInventory::getProductId, productIds));
+        Map<Long, ProductPriceInventory> priceInventoryMap =
+            priceInventoryList.stream()
+                .collect(Collectors.toMap(
+                    ProductPriceInventory::getProductId,
+                    Function.identity(),
+                    (a, b) -> a
+                ));
+        // 3.查询品牌中文或英文名称
+        // 3. 品牌信息(重点)
+        Set<Long> brandIds = productList.stream()
+            .map(ProductBase::getBrandId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+
+        Map<Long, ProductBrand> brandMap = Collections.emptyMap();
+        if (CollUtil.isNotEmpty(brandIds)) {
+            brandMap = productBrandService.list(
+                    new LambdaQueryWrapper<ProductBrand>()
+                        .in(ProductBrand::getId, brandIds)
+                ).stream()
+                .collect(Collectors.toMap(
+                    ProductBrand::getId,
+                    Function.identity()
+                ));
+        }
+        // 4. 组装聚合 DTO
+        Map<Long, ProductBrand> finalBrandMap = brandMap;
+
+        //5.查询单位名称
+        List<Long> unitIds = productList.stream()
+            .map(ProductBase::getUnitId)
+            .filter(Objects::nonNull)
+            .distinct()
+            .toList();
+
+        List<ProductUnit> unitList = productUnitService.list(new LambdaQueryWrapper<ProductUnit>().in(ProductUnit::getId, unitIds));
+        Map<Long, String> unitNameMap = unitList.stream()
+            .collect(Collectors.toMap(
+                ProductUnit::getId,
+                ProductUnit::getUnitName,
+                (a, b) -> a
+            ));
+
+        //6.查询商品描述
+        List<ProductExtend> extendList = productExtendService.list(
+            new LambdaQueryWrapper<ProductExtend>()
+                .in(ProductExtend::getProductId, productIds)
+        );
+
+        Map<Long, String> productDescMap = extendList.stream()
+            .collect(Collectors.toMap(
+                ProductExtend::getProductId,
+                ProductExtend::getProductDescription,
+                (a, b) -> a
+            ));
+
+        //7.查询商品规格
+        List<ProductClassification> productClassificationList = productClassificationService.list(
+            new LambdaQueryWrapper<ProductClassification>()
+                .in(ProductClassification::getProductId, productIds)
+        );
+
+        Map<Long, String> productClassificationMap = productClassificationList.stream()
+            .collect(Collectors.toMap(
+                ProductClassification::getProductId,
+                ProductClassification::getAttributesList,
+                (a, b) -> a
+            ));
+
+
+        // 5. 组装
+        return productList.stream().map(p -> {
+            //TODO 税收编码 写一个伪数据   商品规格没有 就写一个伪数据
+            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());
+            vo.setUnit(unitNameMap.get(p.getUnitId()));
+            vo.setTax(priceInventoryMap.get(p.getId()).getTaxRate());
+
+            //作json处理
+            String productImage = p.getProductImage();
+            if (StrUtil.isNotBlank(productImage)) {
+                List<String> imgList = Arrays.stream(productImage.split(","))
+                    .filter(StrUtil::isNotBlank)
+                    .toList();
+
+                vo.setBarImgUrls(JSONUtil.toJsonStr(imgList));
+            }
+            //作json处理
+            vo.setProperties(
+                Optional.ofNullable(productClassificationMap.get(p.getId()))
+                    .orElse("{\"1\":\"1kg\",\"2\":\"1cm\",\"3\":\"100\"}")
+            );
+
+            vo.setIsSelfOperated(p.getIsSelf());
+
+            // 商品描述
+            vo.setDescription(productDescMap.get(p.getId()));
+            vo.setTaxCode("123456");
+
+            // ===== 品牌名称规则处理 =====
+            ProductBrand brand = finalBrandMap.get(p.getBrandId());
+            if (brand != null) {
+                if (StrUtil.isNotBlank(brand.getBrandName())) {
+                    vo.setBrandName(brand.getBrandName());
+                } else if (StrUtil.isNotBlank(brand.getBrandEnglishName())){
+                    vo.setBrandNameEn(brand.getBrandEnglishName());
+                }else {
+                    vo.setBrandName(p.getItemName());
+                }
+
+            }
+            return vo;
+        }).toList();
+    }
+
 
 
 }
 }