Эх сурвалжийг харах

feat(external): 完善外部商品管理功能

- 替换 Result 为 ZZResult 统一返回格式
- 修改数据库连接配置信息
- 将 minOrderQuantity 类型从 Integer 改为 Long
- 添加产品分类层级结构支持
- 新增批量上下架功能及测试接口
- 实现新的商品导入监听器和模板
- 完善商品推送策略支持更新操作
- 优化商品查询页面展示逻辑
- 添加商品审核相关服务接口
肖路 5 өдөр өмнө
parent
commit
838d46f85b
100 өөрчлөгдсөн 5214 нэмэгдсэн , 395 устгасан
  1. 15 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/domain/ExternalProductDto.java
  2. 96 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderAddBo.java
  3. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderBo.java
  4. 93 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderListBo.java
  5. 57 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyApplyReconBo.java
  6. 33 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAuthBo.java
  7. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyConfirmOrderBo.java
  8. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderBo.java
  9. 82 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderInvoiceBo.java
  10. 88 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderListBo.java
  11. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderStatusBo.java
  12. 41 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductBo.java
  13. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductBrandBo.java
  14. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductDetailBo.java
  15. 38 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductStockBo.java
  16. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductUnitBo.java
  17. 38 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyReconListBo.java
  18. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyReconStateBo.java
  19. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyRootOrderBo.java
  20. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartySetAfterStateBo.java
  21. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartySetOrderPayStateBo.java
  22. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyTrackingBo.java
  23. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyTrackingStatusBo.java
  24. 81 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyAfterOrderDto.java
  25. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyAfterOrderStatusDto.java
  26. 78 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyAreaDto.java
  27. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyAuthDto.java
  28. 175 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyOrderDto.java
  29. 126 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyOrderInvoiceDto.java
  30. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyOrderPayStateDto.java
  31. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyOrderStatusDto.java
  32. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductBrandDto.java
  33. 38 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductCateDto.java
  34. 60 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductDetailDto.java
  35. 125 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductDto.java
  36. 54 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductPriceDto.java
  37. 38 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductStatusDto.java
  38. 43 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductStockDto.java
  39. 28 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyProductUnitDto.java
  40. 34 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyReconDto.java
  41. 23 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyReconStateDto.java
  42. 29 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyRootOrderDto.java
  43. 85 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyTrackingDto.java
  44. 33 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/dto/ThirdpartyTrackingStatusDto.java
  45. 1 0
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongche/domain/ZCR.java
  46. 14 14
      ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongzhi/domain/ZZResult.java
  47. 8 1
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductService.java
  48. 87 34
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductVo.java
  49. 10 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/zhongche/dto/ProductAggregateDto.java
  50. 8 8
      ruoyi-auth/src/main/java/org/dromara/auth/controller/Auth2Controller.java
  51. 10 0
      ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java
  52. 6 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/R.java
  53. 30 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/ThirdpartyCertificationBody.java
  54. 9 0
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java
  55. 13 0
      ruoyi-modules/ruoyi-external/pom.xml
  56. 46 5
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/ExternalProductController.java
  57. 299 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyController.java
  58. 11 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePullController.java
  59. 31 13
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java
  60. 48 48
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongzhi/ZhongZhiPullController.java
  61. 107 107
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongzhi/ZhongZhiPushController.java
  62. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/ExternalProduct.java
  63. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/bo/ExternalProductBo.java
  64. 1 1
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductImportVo.java
  65. 113 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductNewImportVo.java
  66. 2 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductVo.java
  67. 15 4
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalProductServiceImpl.java
  68. 7 5
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java
  69. 138 23
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongChePushStrategy.java
  70. 6 5
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongZhiPushStrategy.java
  71. 10 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/listener/ExternalProductImportListener.java
  72. 177 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/listener/ExternalProductNewImportListener.java
  73. 12 2
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalProductService.java
  74. 10 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductCategoryServiceImpl.java
  75. 98 24
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductServiceImpl.java
  76. 44 44
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/DataMigration.java
  77. 104 0
      ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/ProductPhotoImporter.java
  78. 1 2
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/pc/PcOrderController.java
  79. 126 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductBaseAuditController.java
  80. 20 1
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductBaseController.java
  81. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductCategoryA10Controller.java
  82. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductCategoryCustomerController.java
  83. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductClassificationDiyController.java
  84. 36 8
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductPoolAuditController.java
  85. 73 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductBaseAudit.java
  86. 157 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductCategoryA10.java
  87. 162 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductCategoryCustomer.java
  88. 51 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductClassificationDiy.java
  89. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductPoolAudit.java
  90. 16 6
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductPoolLinkAudit.java
  91. 24 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductAuditBo.java
  92. 79 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseAuditBo.java
  93. 33 17
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseBo.java
  94. 171 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductCategoryA10Bo.java
  95. 177 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductCategoryCustomerBo.java
  96. 52 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductClassificationDiyBo.java
  97. 5 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductPoolAuditBo.java
  98. 13 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductPoolLinkAuditBo.java
  99. 93 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseAuditVo.java
  100. 20 17
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java

+ 15 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/domain/ExternalProductDto.java

@@ -83,4 +83,19 @@ public class ExternalProductDto implements Serializable {
      */
     private Integer connectStatus;
 
+    /**
+    * 申请类型 0更新,1移出
+    * */
+    private Integer type;
+
+    /**
+    * 计价规则(0 一品一价,1 按类目折扣率报价)
+    * */
+    private String pricingRule;
+
+    /**
+    * 起订量
+    * */
+    private Long minOrderQuantity;
+
 }

+ 96 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderAddBo.java

@@ -0,0 +1,96 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 售后订单新增请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAfterOrderAddBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 售后单号
+     */
+    private String orderID;
+
+    /**
+     * 售后金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 售后时间
+     */
+    private Date date;
+
+    /**
+     * 售后状态
+     */
+    private Integer state;
+
+    /**
+     * 售后原因
+     */
+    private String reason;
+
+    /**
+     * 售后描述
+     */
+    private String desc;
+
+    /**
+     * 商品信息
+     */
+    private List<AfterOrderProduct> productIds;
+
+    @Data
+    public static class AfterOrderProduct implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        private Integer id;
+        private String created;
+        private String modify;
+
+        /**
+         * 订单号
+         */
+        private String orderID;
+
+        /**
+         * 商品单号
+         */
+        private String productNo;
+
+        /**
+         * 商品名称
+         */
+        private String name;
+
+        /**
+         * 商品数量
+         */
+        private Integer num;
+
+        /**
+         * 商品单价
+         */
+        private BigDecimal price;
+
+        /**
+         * 商品总金额
+         */
+        private BigDecimal amount;
+    }
+}

+ 23 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderBo.java

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 售后订单查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAfterOrderBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 售后订单号
+     */
+    private String orderID;
+}

+ 93 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAfterOrderListBo.java

@@ -0,0 +1,93 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 售后订单列表查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAfterOrderListBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 当前页
+     */
+    private Integer pageIndex;
+
+    /**
+     * 每页显示数量
+     */
+    private Integer pageSize;
+
+    /**
+     * 数据总行数(非分页)
+     */
+    private Integer dataCount;
+
+    /**
+     * 售后单号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态
+     */
+    private Integer status;
+
+    /**
+     * 支付状态
+     */
+    private Integer paystatus;
+
+    /**
+     * 下单时间
+     */
+    private String ordertime;
+
+    /**
+     * 下单截止时间
+     */
+    private String end_ordertime;
+
+    /**
+     * 发货时间
+     */
+    private String deliverytime;
+
+    /**
+     * 发货截止时间
+     */
+    private String end_deliverytime;
+
+    /**
+     * 签收时间
+     */
+    private String signingtime;
+
+    /**
+     * 签收截止时间
+     */
+    private String end_signingtime;
+
+    /**
+     * 条件
+     */
+    private Integer condition;
+
+    /**
+     * 物流状态
+     */
+    private Integer logisticstatus;
+
+    /**
+     * 发货状态
+     */
+    private Integer deliverystatus;
+}

+ 57 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyApplyReconBo.java

@@ -0,0 +1,57 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 对账申请请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyApplyReconBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 总金额
+     */
+    private BigDecimal totalAmount;
+
+    /**
+     * 申请时间
+     */
+    private Date datetime;
+
+    /**
+     * 申请状态 0未开,1已开
+     */
+    private Integer state;
+
+    /**
+     * 多订单号
+     */
+    private List<OrderIdItem> orderIds;
+
+    @Data
+    public static class OrderIdItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 订单id
+         */
+        private String orderID;
+
+        /**
+         * 对账金额
+         */
+        private BigDecimal amount;
+    }
+}

+ 33 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyAuthBo.java

@@ -0,0 +1,33 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 获取令牌请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAuthBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 平台代码
+     */
+    private String patformID;
+
+    /**
+     * 账户
+     */
+    private String account;
+
+    /**
+     * 秘钥
+     */
+    private String secret;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyConfirmOrderBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 撤销订单请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyConfirmOrderBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态  0-待确认 1-已确认、3-已取消、4-已完成、5-已对账、6-已开票、7-售后中、8-售后完成、9-拒绝售后
+     */
+    private Integer orderstatus;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主订单号
+     */
+    private String parentOrderNo;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+}

+ 82 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderInvoiceBo.java

@@ -0,0 +1,82 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 申请开票请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderInvoiceBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 开票流水号
+     */
+    private String invoicenum;
+
+    /**
+     * 开票金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 发票抬头
+     */
+    private String rise;
+
+    /**
+     * 发票类型0增值税专用,1增值税普通
+     */
+    private Integer type;
+
+    /**
+     * 申请时间
+     */
+    private Date applyDate;
+
+    /**
+     * 开票时间
+     */
+    private Date billingDate;
+
+    /**
+     * 发票状态0未开,1已开
+     */
+    private Integer state;
+
+    /**
+     * 审核状态0未审,1已审
+     */
+    private Integer examine;
+
+    /**
+     * 订单数组
+     */
+    private List<OrderInvoiceItem> orderIds;
+
+    @Data
+    public static class OrderInvoiceItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 订单号
+         */
+        private String orderID;
+
+        /**
+         * 开票金额
+         */
+        private BigDecimal billingAmount;
+    }
+}

+ 88 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderListBo.java

@@ -0,0 +1,88 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单列表查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderListBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 当前页
+     */
+    private Integer pageIndex;
+
+    /**
+     * 每页显示数量
+     */
+    private Integer pageSize;
+
+    /**
+     * 数据总行数(非分页)
+     */
+    private Integer dataCount;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态
+     */
+    private Integer orderstatus;
+
+    /**
+     * 支付状态
+     */
+    private Integer paystatus;
+
+    /**
+     * 下单时间
+     */
+    private String ordertime;
+
+    /**
+     * 下单截止时间
+     */
+    private String end_ordertime;
+
+    /**
+     * 发货时间
+     */
+    private String deliverytime;
+
+    /**
+     * 发货截止时间
+     */
+    private String end_deliverytime;
+
+    /**
+     * 签收时间
+     */
+    private String signingtime;
+
+    /**
+     * 签收截止时间
+     */
+    private String end_signingtime;
+
+    /**
+     * 物流状态
+     */
+    private Integer logisticstatus;
+
+    /**
+     * 发货状态
+     */
+    private Integer deliverystatus;
+}

+ 23 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyOrderStatusBo.java

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单状态查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderStatusBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+}

+ 41 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductBo.java

@@ -0,0 +1,41 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author
+ * @date 2026/4/9 下午1:46
+ */
+@Data
+public class ThirdpartyProductBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    private String itemName;
+
+
+    /**
+     * 三级分类ID
+     */
+    private Long categoryId;
+
+
+    /**
+     * 商品品牌
+     */
+    private Long brandId;
+
+}
+

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductBrandBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品品牌查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductBrandBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 品牌id
+     */
+    private String brandId;
+
+    /**
+     * 品牌名称
+     */
+    private String name;
+}

+ 23 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductDetailBo.java

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品详情查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductDetailBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+}

+ 38 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductStockBo.java

@@ -0,0 +1,38 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 商品库存查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductStockBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品编码
+     */
+    private String productNo;
+
+    /**
+     * 省
+     */
+    private Integer provinceId;
+
+    /**
+     * 市
+     */
+    private Integer cityId;
+
+    /**
+     * 县/区
+     */
+    private Integer countyId;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyProductUnitBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品单位查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductUnitBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 单位id
+     */
+    private String unitId;
+
+    /**
+     * 单位名称
+     */
+    private String name;
+}

+ 38 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyReconListBo.java

@@ -0,0 +1,38 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 对账列表查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyReconListBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 当前页
+     */
+    private Integer pageIndex;
+
+    /**
+     * 每页显示数量
+     */
+    private Integer pageSize;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 对账状态 0未开,1已开
+     */
+    private Integer state;
+}

+ 23 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyReconStateBo.java

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 对账状态查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyReconStateBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 对账单号
+     */
+    private String reconNo;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyRootOrderBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 主订单查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyRootOrderBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主订单单号
+     */
+    private String parentOrderNo;
+
+    /**
+     * 子订单号
+     */
+    private String orderID;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartySetAfterStateBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 售后订单状态修改请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartySetAfterStateBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 售后订单号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态0-申请 1-已确认、2-已取消、3-售后中、4-售后完成、5-拒绝售后
+     */
+    private Integer state;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartySetOrderPayStateBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单支付状态写入请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartySetOrderPayStateBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 支付状态  0-待支付 1-已支付
+     */
+    private Integer paystatus;
+}

+ 28 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyTrackingBo.java

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 物流查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyTrackingBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 包裹Id
+     */
+    private String packageId;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+}

+ 23 - 0
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/thirdparty/domain/bo/ThirdpartyTrackingStatusBo.java

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 物流状态查询请求参数
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyTrackingStatusBo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 物流单号
+     */
+    private String logisticsNo;
+}

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

@@ -0,0 +1,81 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 售后订单响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAfterOrderDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态0-申请 1-已确认、2-已取消、3-售后中、4-售后完成、5-拒绝售后
+     */
+    private String state;
+
+    /**
+     * 售后原因
+     */
+    private String reason;
+
+    /**
+     * 下单时间yyyymmddhh24miss
+     */
+    private String ordertime;
+
+    /**
+     * 商品信息
+     */
+    private List<AfterOrderProduct> productIds;
+
+    @Data
+    public static class AfterOrderProduct implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        private Integer id;
+        private String created;
+        private String modify;
+        private String orderID;
+
+        /**
+         * 商品单号
+         */
+        private String productNo;
+
+        /**
+         * 商品名称
+         */
+        private String name;
+
+        /**
+         * 商品数量
+         */
+        private Integer num;
+
+        /**
+         * 商品单价
+         */
+        private BigDecimal price;
+
+        /**
+         * 订单总金额,含运费,单位分
+         */
+        private String amount;
+    }
+}

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

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 售后订单状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAfterOrderStatusDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 售后订单号
+     */
+    private String orderID;
+
+    /**
+     * 状态
+     */
+    private Integer state;
+}

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

@@ -0,0 +1,78 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 区域地址响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAreaDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * keyId
+     */
+    private Integer keyId;
+
+    /**
+     * 区域代码
+     */
+    private String areaCode;
+
+    /**
+     * 区域名称
+     */
+    private String areaName;
+
+    /**
+     * 父级代码
+     */
+    private Integer parentCode;
+
+    /**
+     * 简称
+     */
+    private String simpleName;
+
+    /**
+     * 层级
+     */
+    private Integer level;
+
+    /**
+     * 城市代码
+     */
+    private String cityCode;
+
+    /**
+     * 邮政编码
+     */
+    private String zipCode;
+
+    /**
+     * 完整名称
+     */
+    private String merName;
+
+    /**
+     * 经度
+     */
+    private Double lng;
+
+    /**
+     * 纬度
+     */
+    private Double lat;
+
+    /**
+     * 拼音
+     */
+    private String pinYin;
+}

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

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 获取令牌响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyAuthDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * token令牌
+     */
+    private String token;
+}

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

@@ -0,0 +1,175 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 订单响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 下单客户名称(三方平台下客户)
+     */
+    private String ordercustname;
+
+    /**
+     * 收货人
+     */
+    private String receiver;
+
+    /**
+     * 省份id
+     */
+    private String province;
+
+    /**
+     * 城市id
+     */
+    private String city;
+
+    /**
+     * 区域id
+     */
+    private String county;
+
+    /**
+     * 乡镇id
+     */
+    private String town;
+
+    /**
+     * 收货地址-详细地址
+     */
+    private String address;
+
+    /**
+     * 邮编
+     */
+    private String zipcode;
+
+    /**
+     * 联系人手机
+     */
+    private String mobilecall;
+
+    /**
+     * 联系人座机
+     */
+    private String phoneno;
+
+    /**
+     * 支付方式0-货到付款、1-账期
+     */
+    private Integer paymode;
+
+    /**
+     * 订单总金额,含运费,单位分
+     */
+    private BigDecimal feetotal;
+
+    /**
+     * 支付状态0-待支付 1-已支付
+     */
+    private Integer paystatus;
+
+    /**
+     * 订单状态0-待确认 1-已确认、3-已取消、4-已完成、5-已对账、6-已开票、7-售后中、8-售后完成、9-拒绝售后
+     */
+    private Integer orderstatus;
+
+    /**
+     * 物流状态:0-待发货、1-发货中、2-已签收、3-拒签
+     */
+    private Integer LogisticsStatus;
+
+    /**
+     * 订单备注
+     */
+    private String ordermemo;
+
+    /**
+     * 期望收货时间yyyymmdd
+     */
+    private String orderexpectdt;
+
+    /**
+     * 下单时间yyyymmddhh24miss
+     */
+    private String ordercreatetm;
+
+    /**
+     * 同步状态1-已上传0-未上传
+     */
+    private Integer ordersyncsign;
+
+    /**
+     * 商品总金额单位分
+     */
+    private BigDecimal productprice;
+
+    /**
+     * 运费单位分
+     */
+    private BigDecimal freight;
+
+    /**
+     * SKU信息
+     */
+    private List<OrderSkuInfo> skuinfo;
+
+    @Data
+    public static class OrderSkuInfo implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        private Integer id;
+        private String created;
+        private String modify;
+
+        /**
+         * 订单编号
+         */
+        private String orderID;
+
+        /**
+         * 商品编号
+         */
+        private String productNo;
+
+        /**
+         * 商品名称
+         */
+        private String itemName;
+
+        /**
+         * 销售价
+         */
+        private BigDecimal salePrice;
+
+        /**
+         * 供应价
+         */
+        private BigDecimal supplyPrice;
+
+        /**
+         * 数量
+         */
+        private Integer shopNum;
+    }
+}

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

@@ -0,0 +1,126 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 开票信息响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderInvoiceDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 开票流水号
+     */
+    private String invoicenum;
+
+    /**
+     * 平台id
+     */
+    private String PatformID;
+
+    /**
+     * 开票金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 开票抬头
+     */
+    private String rise;
+
+    /**
+     * 发票类型0增值税专用,1增值税普通
+     */
+    private Integer type;
+
+    /**
+     * 订单数组
+     */
+    private List<OrderInvoiceItem> orderIds;
+
+    /**
+     * 申请时间
+     */
+    private String applyDate;
+
+    /**
+     * 开票时间
+     */
+    private String billingDate;
+
+    /**
+     * 发票状态0未开,1已开
+     */
+    private Integer state;
+
+    /**
+     * 审核状态0未审,1已审
+     */
+    private Integer examine;
+
+    /**
+     * 物流信息
+     */
+    private List<LogisticsInfo> logistics;
+
+    @Data
+    public static class OrderInvoiceItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 订单号
+         */
+        private String orderID;
+
+        /**
+         * 开票金额
+         */
+        private BigDecimal billingAmount;
+    }
+
+    @Data
+    public static class LogisticsInfo implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        private Integer id;
+        private String created;
+        private String modify;
+
+        /**
+         * 发票流水号
+         */
+        private String invoicenum;
+
+        /**
+         * 物流id
+         */
+        private String logisticsID;
+
+        /**
+         * 物流名称
+         */
+        private String name;
+
+        /**
+         * 物流编号
+         */
+        private String no;
+
+        /**
+         * 物流状态
+         */
+        private Integer state;
+    }
+}

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

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单支付状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderPayStateDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 支付状态  0-待支付 1-已支付
+     */
+    private Integer paystate;
+}

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

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 订单状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyOrderStatusDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 订单状态  0-待确认 1-已确认、3-已取消、4-已完成、5-已对账、6-已开票、7-售后中、8-售后完成、9-拒绝售后
+     */
+    private Integer status;
+}

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

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品品牌响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductBrandDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 品牌id
+     */
+    private String brandId;
+
+    /**
+     * 品牌名称
+     */
+    private String name;
+}

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

@@ -0,0 +1,38 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品分类响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductCateDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 分类id
+     */
+    private String id;
+
+    /**
+     * 父级id
+     */
+    private String parentId;
+
+    /**
+     * 分类层级
+     */
+    private Integer catLevel;
+
+    /**
+     * 分类名称
+     */
+    private String name;
+}

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

@@ -0,0 +1,60 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 产品详情响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductDetailDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品id
+     */
+    private String productId;
+
+    /**
+     * 商品编码
+     */
+    private String productNo;
+
+    /**
+     * 商品名称
+     */
+    private String itemName;
+
+    /**
+     * 商品图片
+     */
+    private String photo;
+
+    /**
+     * 商品多图
+     */
+    private List<ProductImage> productImages;
+
+    /**
+     * 产品详情
+     */
+    private String content;
+
+    @Data
+    public static class ProductImage implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 图片URL
+         */
+        private String imageUrl;
+    }
+}

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

@@ -0,0 +1,125 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 商品数据
+ *
+ * @author
+ * @date 2026/4/9 上午11:45
+ */
+@Data
+public class ThirdpartyProductDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 商品主图
+     */
+    private String photo;
+
+    /**
+     * 商品多图
+     */
+    private String productImages;
+
+    /**
+     * 商品详情
+     */
+    private String content;
+
+    /**
+     * 产品名称
+     */
+    private String itemName;
+
+    /**
+     * 一级分类ID
+     */
+    private String cateLable;
+
+    /**
+     * 二级分类ID
+     */
+    private String cateLevel;
+
+    /**
+     * 三级分类ID
+     */
+    private String cateProduct;
+
+    /**
+     * 单位名称(如:件、箱、千克等)
+     */
+    private String pdunit;
+
+    /**
+     * 市场价
+     */
+    private BigDecimal pdpricemarket;
+
+    /**
+     * 平台价格
+     */
+    private BigDecimal pdpricemall;
+
+    /**
+     * 供应价格
+     */
+    private BigDecimal pdpricesale;
+
+    /**
+     * 折扣率
+     */
+    private String pddiscount;
+
+    /**
+     * 上下架状态:3=上架,4=下架
+     */
+    private Integer pdStatus;
+
+    /**
+     * 商品卖点
+     */
+    private String pdhotpoint;
+
+    /**
+     * 起订量
+     */
+    private Integer pdsaleunit;
+
+    /**
+     * 品牌名称
+     */
+    private String brandName;
+
+    /**
+     * 售后信息
+     */
+    private String pdsaleinfo;
+
+    /**
+     * 商品属性
+     */
+    private String attributes;
+
+    /**
+     * 可用库存数量
+     */
+    private Integer availableStockNum;
+
+    /**
+     * 占用库存数量
+     */
+    private Integer occupyStockNum;
+
+}

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

@@ -0,0 +1,54 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 产品价格响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductPriceDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品id
+     */
+    private String id;
+
+    /**
+     * 商品编码
+     */
+    private String productNo;
+
+    /**
+     * 商品名称
+     */
+    private String itemName;
+
+    /**
+     * 市场价格
+     */
+    private BigDecimal pdpricemarket;
+
+    /**
+     * 平台价格
+     */
+    private BigDecimal pdpricemall;
+
+    /**
+     * 供应价格
+     */
+    private BigDecimal pdpricesale;
+
+    /**
+     * 折扣率
+     */
+    private String pddiscount;
+}

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

@@ -0,0 +1,38 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductStatusDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品id
+     */
+    private Integer id;
+
+    /**
+     * 商品编码
+     */
+    private String productNo;
+
+    /**
+     * 商品名称
+     */
+    private String itemName;
+
+    /**
+     * 产品状态3-上架4-下架
+     */
+    private Integer pdstatus;
+}

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

@@ -0,0 +1,43 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 商品库存响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductStockDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 商品编码
+     */
+    private String productNo;
+
+    /**
+     * 省
+     */
+    private String provinceId;
+
+    /**
+     * 市
+     */
+    private String cityId;
+
+    /**
+     * 县/区
+     */
+    private String countyId;
+
+    /**
+     * 库存数量
+     */
+    private Integer num;
+}

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

@@ -0,0 +1,28 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 产品单位响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyProductUnitDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 单位id
+     */
+    private String unitId;
+
+    /**
+     * 单位名称
+     */
+    private String name;
+}

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

@@ -0,0 +1,34 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 对账响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyReconDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 对账状态信息
+     */
+    private Integer state;
+
+    /**
+     * 对账金额
+     */
+    private BigDecimal amount;
+}

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

@@ -0,0 +1,23 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 对账状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyReconStateDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 状态
+     */
+    private String state;
+}

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

@@ -0,0 +1,29 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 主订单响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyRootOrderDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主订单单号
+     */
+    private String parentOrderNo;
+
+    /**
+     * 子订单列表
+     */
+    private List<String> childOrders;
+}

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

@@ -0,0 +1,85 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 物流响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyTrackingDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 包裹id
+     */
+    private String packageId;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 物流名称
+     */
+    private String distrName;
+
+    /**
+     * 物流单号
+     */
+    private String logisticsNo;
+
+    /**
+     * 发货时间系统时间
+     */
+    private String msgTime;
+
+    /**
+     * 0自有物流,1第三方物流
+     */
+    private Integer type;
+
+    /**
+     * 物流状态0-待发货、1-发货中、2-已签收、3-拒签(只有当 type =0时此字段才有效)
+     */
+    private Integer logisticsStates;
+
+    /**
+     * 订单商品信息
+     */
+    private List<OrderItem> orderItelist;
+
+    /**
+     * 物流信息
+     */
+    private String logisticsInfo;
+
+    @Data
+    public static class OrderItem implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 商品id
+         */
+        private String productNo;
+
+        /**
+         * 商品数量
+         */
+        private Integer num;
+
+        /**
+         * 商品名称
+         */
+        private String itemName;
+    }
+}

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

@@ -0,0 +1,33 @@
+package org.dromara.external.api.thirdparty.domain.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 物流状态响应数据
+ *
+ * @author
+ * @date 2026/4/9
+ */
+@Data
+public class ThirdpartyTrackingStatusDto implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 订单编号
+     */
+    private String orderID;
+
+    /**
+     * 包裹id
+     */
+    private String packageId;
+
+    /**
+     * 物流状态:0-待发货、1-发货中、2-已签收、3-拒签
+     */
+    private Integer LogisticsStatus;
+}

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

@@ -7,6 +7,7 @@ import java.io.Serial;
 import java.io.Serializable;
 
 /**
+ * 中车接口返回对象
  * author
  * 时间:2026/1/5,19:16
  */

+ 14 - 14
ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongzhi/domain/Result.java → ruoyi-api/ruoyi-api-external/src/main/java/org/dromara/external/api/zhongzhi/domain/ZZResult.java

@@ -8,7 +8,7 @@ import java.io.Serializable;
 
 @Data
 @NoArgsConstructor
-public class Result<T> implements Serializable {
+public class ZZResult<T> implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
@@ -30,33 +30,33 @@ public class Result<T> implements Serializable {
     private T result;
 
 
-    public static <T> Result<T> tokenOk(String accessToken,String expires_at) {
+    public static <T> ZZResult<T> tokenOk(String accessToken, String expires_at) {
         return restResult(SUCCESS, 200,accessToken,expires_at, "",null);
     }
 
 
-    public static <T> Result<T> ok(T result) {
+    public static <T> ZZResult<T> ok(T result) {
         return restResult(SUCCESS, 200, "", "", "",result);
     }
 
-    public static <T> Result<T> ok(String msg, T result) {
+    public static <T> ZZResult<T> ok(String msg, T result) {
         return restResult(SUCCESS, 200, "", "", msg,result);
     }
 
-    public static <T> Result<T> fail(int code,String msg) {
+    public static <T> ZZResult<T> fail(int code, String msg) {
         return restResult(FAIL, code, "","",msg,null);
     }
 
 
 
-    private static <T>Result<T> restResult(boolean success,int code, String accessToken, String expires_at,String desc,T result) {
-        Result Result = new Result();
-        Result.setResult( result);
-        Result.setSuccess(success);
-        Result.setCode(code);
-        Result.setAccess_token(accessToken);
-        Result.setExpires_at(expires_at);
-        Result.setDesc(desc);
-        return Result;
+    private static <T> ZZResult<T> restResult(boolean success, int code, String accessToken, String expires_at, String desc, T result) {
+        ZZResult ZZResult = new ZZResult();
+        ZZResult.setResult( result);
+        ZZResult.setSuccess(success);
+        ZZResult.setCode(code);
+        ZZResult.setAccess_token(accessToken);
+        ZZResult.setExpires_at(expires_at);
+        ZZResult.setDesc(desc);
+        return ZZResult;
     }
 }

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

@@ -38,7 +38,13 @@ public interface RemoteProductService {
     /**
     * 获取多个商品详情
     * */
-    List<ProductVo> getProductDetails(String productIds);
+    List<ProductVo> getProductDetails(List<Long> productIds);
+
+    /**
+    * 获取多个商品详情
+    * */
+    List<ProductVo> getProductDetailsByNo(String productNos);
+
 
     /**
     * 获取商品变更记录
@@ -119,4 +125,5 @@ public interface RemoteProductService {
      */
     Long getProductIdProductNo(String productNo);
 
+
 }

+ 87 - 34
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ProductVo.java

@@ -5,6 +5,8 @@ import lombok.Data;
 import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 
 /**
@@ -60,18 +62,38 @@ public class ProductVo implements Serializable {
     private Long bottomCategoryId;
 
     /**
-    * 分类名称
-    * */
+     * 分类名称(底级分类)
+     */
     private String categoryName;
 
+    /**
+     * 顶级分类名称
+     */
+    private String topCategoryName;
+
+    /**
+     * 中级分类名称
+     */
+    private String mediumCategoryName;
+
+    /**
+     * 底级分类名称
+     */
+    private String bottomCategoryName;
+
+    /**
+     * 规格代码
+     */
+    private String specificationsCode;
+
     /**
      * 单位id
      */
     private String unitId;
 
     /**
-    * 单位名称
-    * */
+     * 单位名称(如:件、箱、千克等)
+     */
     private String unitName;
 
     /**
@@ -79,21 +101,26 @@ public class ProductVo implements Serializable {
      */
     private String productImage;
 
-    /**
-     * 产品图片URLUrl
-     */
-    private String productImageUrl;
     /**
      * 是否自营(1=是,0=否)
      */
     private Integer isSelf;
 
+    /**
+     * 商品类型 1=默认类型,2精选商品,3=停售商品
+     * */
+    private Integer productCategory;
+
     /**
      * 产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回
      */
-
     private Integer productReviewStatus;
 
+    /**
+     * 审核意见
+     * */
+    private String reviewComments;
+
     /**
      * 首页推荐:1=推荐,0=不推荐
      */
@@ -127,7 +154,7 @@ public class ProductVo implements Serializable {
     /**
      * 商品状态:1=已上架,0=下架 2 上架中等
      */
-    Integer productStatus;
+    private Integer productStatus;
 
     /**
      * 数据来源
@@ -135,8 +162,8 @@ public class ProductVo implements Serializable {
     private String dataSource;
 
     /**
-    * 市场价
-    * */
+     * 市场价
+     * */
     private BigDecimal marketPrice;
 
     /**
@@ -155,16 +182,10 @@ public class ProductVo implements Serializable {
     private BigDecimal purchasingPrice;
 
 
-
-    /**
-    * 暂估毛利率
-    * */
-    private BigDecimal tempGrossMargin;
-
     /**
-     * 总库存
+     * 暂估毛利率
      * */
-    private Long totalInventory;
+    private BigDecimal tempGrossMargin;
 
 
     /**
@@ -185,7 +206,7 @@ public class ProductVo implements Serializable {
     /**
      * UPC(S)条码
      */
-    private String upcBarcode;
+    private String barCoding;
 
     /**
      * 发票名称
@@ -195,7 +216,7 @@ public class ProductVo implements Serializable {
     /**
      * 发票规格
      */
-    private String invoiceSpec;
+    private String invoiceSpecs;
 
     /**
      * 包装规格
@@ -210,7 +231,7 @@ public class ProductVo implements Serializable {
     /**
      * 商品重量
      */
-    private String weight;
+    private String productWeight;
 
     /**
      * 重量单位
@@ -220,7 +241,7 @@ public class ProductVo implements Serializable {
     /**
      * 商品体积
      */
-    private String volume;
+    private String productVolume;
 
     /**
      * 体积单位
@@ -270,7 +291,6 @@ public class ProductVo implements Serializable {
     /**
      * 平档价
      */
-
     private BigDecimal standardPrice;
 
     /**
@@ -278,15 +298,11 @@ public class ProductVo implements Serializable {
      */
     private BigDecimal certificatePrice;
 
-    /**
-     * 采购价
-     */
-    private BigDecimal purchasePrice;
 
     /**
-     * 暂估采购价
+     * 最高采购价
      */
-    private BigDecimal estimatedPurchasePrice;
+    private BigDecimal maxPurchasePrice;
 
     /**
      * 产品经理
@@ -298,6 +314,11 @@ public class ProductVo implements Serializable {
      */
     private String purchasingPersonnel;
 
+    /**
+     * 商品多图
+     * */
+    private String imageUrl;
+
     /**
      * 商品详情 - 电脑端
      */
@@ -324,9 +345,24 @@ public class ProductVo implements Serializable {
     private Long minOrderQuantity;
 
     /**
-     * 是否可定制
-     */
-    private Boolean customizable;
+     * 是否可定制 0:不可定制 1:可定制
+     * */
+    private String isCustomize;
+
+    /**
+     * 总库存
+     * */
+    private Long totalInventory;
+    /**
+     * 当前可用库存
+     * */
+    private Long nowInventory;
+
+    /**
+     * 虚拟库存
+     * */
+    private Long virtualInventory;
+
 
     /**
      * 定制说明
@@ -363,4 +399,21 @@ public class ProductVo implements Serializable {
      */
     private String customizedCraft;
 
+
+    /**
+     * 上架审核评论
+     * */
+    private String shelfComments;
+
+    /**
+     * 协议价
+     * */
+    private BigDecimal agreementPrice;
+
+    /**
+    * 商品描述
+    * */
+    private String productDescription;
+
+
 }

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

@@ -49,4 +49,14 @@ public class ProductAggregateDto implements Serializable {
     private String categoryName;
 
     private String invoiceName;
+
+    private String goodsUrl;
+
+    private String thirdUrl;
+
+
+    /**
+     * 自定义属性
+     * */
+    private String diyAttributesList;
 }

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

@@ -19,7 +19,7 @@ import org.dromara.external.api.zhongche.domain.ZCR;
 import org.dromara.external.api.zhongche.domain.bo.UserLoginBo;
 import org.dromara.external.api.zhongche.domain.bo.ZCTokenBo;
 import org.dromara.external.api.zhongche.domain.vo.ZCLoginBusinessRespVo;
-import org.dromara.external.api.zhongzhi.domain.Result;
+import org.dromara.external.api.zhongzhi.domain.ZZResult;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -57,10 +57,10 @@ public class Auth2Controller {
      * 获取 Access Token  ZHONGZHI
      * @param username 用户名
      * @param password 密码(明文,生产环境建议加密后再传)
-     * @return 包含 access_token 和 expires_at 的 Result,失败则 success=false
+     * @return 包含 access_token 和 expires_at 的 ZZResult,失败则 success=false
      */
     @PostMapping("/zhongzhi/access_token")
-    public Result getAccessTokenZhongZhi(String timestamp, String username, String password, String sign) {
+    public ZZResult getAccessTokenZhongZhi(String timestamp, String username, String password, String sign) {
         // 2. 生成 sign = MD5(username + password + timestamp + password).toLowerCase()
         String signStr = username + password + timestamp + password;
         String sign1 = SecureUtil.md5(signStr).toLowerCase();
@@ -68,16 +68,16 @@ public class Auth2Controller {
         if(Objects.equals(sign1,sign)){
             LoginVo loginVo = IAuthStrategy.getAccessToken(username, password);
             if(ObjectUtil.isEmpty(loginVo)){
-                return Result.fail(5002,"授权失败");
+                return ZZResult.fail(5002,"授权失败");
             }
             if(ObjectUtil.isNotEmpty(loginVo.getMsg())){
-                return Result.fail(loginVo.getCode(),loginVo.getMsg());
+                return ZZResult.fail(loginVo.getCode(),loginVo.getMsg());
             }
             DateTime date = DateUtil.offsetSecond(DateUtil.date(), (int) StpUtil.getTokenTimeout(loginVo.getAccessToken()));
             String format = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss");
-            return  Result.tokenOk(loginVo.getAccessToken(), format);
+            return  ZZResult.tokenOk(loginVo.getAccessToken(), format);
         } else  {
-            return Result.fail(5004,"签名错误,请检查后重试");
+            return ZZResult.fail(5004,"签名错误,请检查后重试");
         }
     }
     /**
@@ -89,7 +89,7 @@ public class Auth2Controller {
      * 电商系统域名(生产):apipre.yoe365.com
      * 登录用户名:api_zczc_202403166035
      * 登陆密码:brsa1odzd28xnqz4
-     * @return 包含 access_token 和 expires_at 的 Result,失败则 success=false
+     * @return 包含 access_token 和 expires_at 的 ZZResult,失败则 success=false
      */
     @PostMapping("/zhongche/access_token")
     public ZCR getAccessTokenZhongChe(@RequestBody ZCTokenBo zcTokenBo) {

+ 10 - 0
ruoyi-auth/src/main/java/org/dromara/auth/controller/TokenController.java

@@ -23,6 +23,7 @@ import org.dromara.auth.service.SysLoginService;
 import org.dromara.common.core.constant.SystemConstants;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.domain.model.LoginBody;
+import org.dromara.common.core.domain.model.ThirdpartyCertificationBody;
 import org.dromara.common.core.utils.*;
 import org.dromara.common.encrypt.annotation.ApiEncrypt;
 import org.dromara.common.json.utils.JsonUtils;
@@ -254,4 +255,13 @@ public class TokenController {
         return R.ok(loginVo);
     }
 
+    /**
+    * 获取令牌
+    * */
+    @PostMapping("/requestToken")
+    public R<LoginVo> requestToken(@RequestBody ThirdpartyCertificationBody body) {
+
+        return R.ok();
+    }
+
 }

+ 6 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/R.java

@@ -34,6 +34,11 @@ public class R<T> implements Serializable {
      */
     private int code;
 
+    /**
+     * 是否成功
+     * */
+    private boolean success;
+
     /**
      * 消息内容
      */
@@ -105,6 +110,7 @@ public class R<T> implements Serializable {
         R<T> r = new R<>();
         r.setCode(code);
         r.setData(data);
+        r.setSuccess(HttpStatus.SUCCESS == code);
         r.setMsg(msg);
         return r;
     }

+ 30 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/ThirdpartyCertificationBody.java

@@ -0,0 +1,30 @@
+package org.dromara.common.core.domain.model;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 第三方认证登录参数
+ * @author
+ * @date 2026/4/9 下午2:45
+ */
+@Data
+@NoArgsConstructor
+public class ThirdpartyCertificationBody {
+
+    /**
+    * 平台id
+    * */
+    private String patformID;
+
+    /**
+    * 账户
+    * */
+    private String account;
+
+
+    /**
+    * 密钥
+    * */
+    private String secret;
+}

+ 9 - 0
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/page/TableDataInfo.java

@@ -38,6 +38,11 @@ public class TableDataInfo<T> implements Serializable {
      */
     private int code;
 
+    /**
+     * 是否成功
+     * */
+    private boolean success;
+
     /**
      * 消息内容
      */
@@ -52,6 +57,7 @@ public class TableDataInfo<T> implements Serializable {
     public TableDataInfo(List<T> list, long total) {
         this.rows = list;
         this.total = total;
+        this.success = true;
     }
 
     /**
@@ -60,6 +66,7 @@ public class TableDataInfo<T> implements Serializable {
     public static <T> TableDataInfo<T> build(IPage<T> page) {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setSuccess(true);
         rspData.setMsg("查询成功");
         rspData.setRows(page.getRecords());
         rspData.setTotal(page.getTotal());
@@ -72,6 +79,7 @@ public class TableDataInfo<T> implements Serializable {
     public static <T> TableDataInfo<T> build(List<T> list) {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setSuccess(true);
         rspData.setMsg("查询成功");
         rspData.setRows(list);
         rspData.setTotal(list.size());
@@ -84,6 +92,7 @@ public class TableDataInfo<T> implements Serializable {
     public static <T> TableDataInfo<T> build() {
         TableDataInfo<T> rspData = new TableDataInfo<>();
         rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setSuccess(true);
         rspData.setMsg("查询成功");
         rspData.setRows(new ArrayList<>());
         return rspData;

+ 13 - 0
ruoyi-modules/ruoyi-external/pom.xml

@@ -150,6 +150,19 @@
                     <mainClass>org.dromara.external.RuoyiExternalApplication</mainClass>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.5.3</version>
+                <configuration>
+                    <skipTests>false</skipTests>
+                    <includes>
+                        <include>**/*Test.java</include>
+                        <include>**/*Tests.java</include>
+                        <include>**/Test*.java</include>
+                    </includes>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 

+ 46 - 5
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/ExternalProductController.java

@@ -9,10 +9,14 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.handler.ProductPushStrategyFactory;
 import org.dromara.external.listener.ExternalProductImportListener;
 import org.dromara.external.domain.vo.ExternalProductImportVo;
+import org.dromara.external.listener.ExternalProductNewImportListener;
+import org.dromara.external.domain.vo.ExternalProductNewImportVo;
+import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.ProductVo;
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
@@ -48,6 +52,9 @@ public class ExternalProductController extends BaseController {
 
     private final IExternalProductService externalProductService;
 
+    @DubboReference
+    private RemoteProductService remoteProductService;
+
 
 
     /**
@@ -143,6 +150,24 @@ public class ExternalProductController extends BaseController {
         return toAjax(externalProductService.shelfReview(bo));
     }
 
+    /**
+    * 批量上下架
+    * */
+    @PostMapping("/batchShelfReview")
+    public R<Void> batchShelfReview(@Validated @RequestBody List<ExternalProductBo> externalProductBos) {
+        externalProductService.batchShelfReview(externalProductBos);
+        return R.ok();
+    }
+
+    /**
+    * 测试批量上下架
+    * */
+    @PostMapping("/batchShelfReviewTest")
+    public R<Void> batchShelfReviewTest(@RequestParam String[] productNos, @RequestParam Integer status) {
+        externalProductService.batchShelfReviewTest(productNos, status);
+        return R.ok();
+    }
+
     /**
      * 批量新增对接商品
      * @param itemId
@@ -202,18 +227,34 @@ public class ExternalProductController extends BaseController {
         ExcelResult<ExternalProductImportVo> result = ExcelUtil.importExcel(
             file.getInputStream(),
             ExternalProductImportVo.class,
-            new ExternalProductImportListener(externalProductService)
+            new ExternalProductImportListener(externalProductService,remoteProductService)
+        );
+        return R.ok(result.getAnalysis());
+    }
+
+    /**
+     * 导入对外部推送商品数据(新模板)
+     *
+     * @param file 导入文件
+     */
+    @Log(title = "对外部推送商品导入", businessType = BusinessType.IMPORT)
+    @PostMapping(value = "/importDataNew", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importDataNew(@RequestPart("file") MultipartFile file) throws Exception {
+        ExcelResult<ExternalProductNewImportVo> result = ExcelUtil.importExcel(
+            file.getInputStream(),
+            ExternalProductNewImportVo.class,
+            new ExternalProductNewImportListener(externalProductService,remoteProductService)
         );
         return R.ok(result.getAnalysis());
     }
 
     /**
-     * 获取导入模板
+     * 获取导入模板(新模板)
      */
     @Log(title = "对外部推送商品", businessType = BusinessType.IMPORT)
-    @PostMapping("/importTemplate")
-    public void importTemplate(HttpServletResponse response) {
-        ExcelUtil.exportExcel(new ArrayList<>(), "对外部推送商品模板", ExternalProductImportVo.class, response);
+    @PostMapping("/importTemplateNew")
+    public void importTemplateNew(HttpServletResponse response) {
+        ExcelUtil.exportExcel(new ArrayList<>(), "外部商品导入模板", ExternalProductNewImportVo.class, response);
     }
 
 

+ 299 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/thirdparty/ThirdpartyController.java

@@ -0,0 +1,299 @@
+package org.dromara.external.controller.thirdparty;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.external.api.thirdparty.domain.bo.*;
+import org.dromara.external.api.thirdparty.domain.dto.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 第三方平台接口对接控制器
+ * 优易达(武汉)有限公司-平台接口对接稳定V2.0
+ * 时间:2026/1/5,19:03
+ */
+@Slf4j
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api/thirdparty")
+public class ThirdpartyController {
+
+    /**
+     * 产品列表查询
+     */
+    @PostMapping("/product/getListProducts")
+    public TableDataInfo<ThirdpartyProductDto> getListProducts(@RequestBody ThirdpartyProductBo bo, PageQuery pageQuery) {
+        // TODO: 实现产品列表查询逻辑
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 产品表体接口
+     */
+    @PostMapping("/product/getProductBody")
+    public R<ThirdpartyProductDto> getProductBody(@RequestBody ThirdpartyProductDetailBo bo) {
+        // TODO: 实现产品表体查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品详情查询
+     */
+    @PostMapping("/product/getProductDetails")
+    public R<ThirdpartyProductDetailDto> getProductDetails(@RequestBody ThirdpartyProductDetailBo bo) {
+        // TODO: 实现产品详情查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品价格查询
+     */
+    @PostMapping("/product/getPrice")
+    public R<ThirdpartyProductPriceDto> getPrice(@RequestBody ThirdpartyProductDetailBo bo) {
+        // TODO: 实现产品价格查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 商品查询价格(批量)
+     */
+    @PostMapping("/product/getBatchPrice")
+    public R<List<ThirdpartyProductPriceDto>> getBatchPrice(@RequestBody ThirdpartyProductDetailBo bo) {
+        // TODO: 实现批量价格查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 商品库存查询
+     */
+    @PostMapping("/product/getProductStock")
+    public R<ThirdpartyProductStockDto> getProductStock(@RequestBody ThirdpartyProductStockBo bo) {
+        // TODO: 实现商品库存查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品状态查询
+     */
+    @PostMapping("/product/getStatus")
+    public R<ThirdpartyProductStatusDto> getStatus(@RequestBody ThirdpartyProductDetailBo bo) {
+        // TODO: 实现产品状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品品牌查询
+     */
+    @PostMapping("/product/getProductBrand")
+    public R<List<ThirdpartyProductBrandDto>> getProductBrand(@RequestBody ThirdpartyProductBrandBo bo) {
+        // TODO: 实现产品品牌查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品单位查询
+     */
+    @PostMapping("/product/getProductUnit")
+    public R<ThirdpartyProductUnitDto> getProductUnit(@RequestBody ThirdpartyProductUnitBo bo) {
+        // TODO: 实现产品单位查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 产品分类查询
+     */
+    @PostMapping("/product/getProductCates")
+    public R<List<ThirdpartyProductCateDto>> getProductCates() {
+        // TODO: 实现产品分类查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 获取区域地址
+     */
+    @PostMapping("/Product/getSysArea")
+    public R<List<ThirdpartyAreaDto>> getSysArea() {
+        // TODO: 实现获取区域地址逻辑
+        return R.ok();
+    }
+
+    /**
+     * 订单查询
+     */
+    @PostMapping("/order/getOrder")
+    public R<ThirdpartyOrderDto> getOrder(@RequestBody ThirdpartyOrderBo bo) {
+        // TODO: 实现订单查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 订单列表查询
+     */
+    @PostMapping("/order/getOrders")
+    public TableDataInfo<ThirdpartyOrderDto> getOrders(@RequestBody ThirdpartyOrderListBo bo, PageQuery pageQuery) {
+        // TODO: 实现订单列表查询逻辑
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 主订单查询
+     */
+    @PostMapping("/order/getRootOrder")
+    public R<ThirdpartyRootOrderDto> getRootOrder(@RequestBody ThirdpartyRootOrderBo bo) {
+        // TODO: 实现主订单查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 订单状态查询
+     */
+    @PostMapping("/order/getOrderStatus")
+    public R<ThirdpartyOrderStatusDto> getOrderStatus(@RequestBody ThirdpartyOrderStatusBo bo) {
+        // TODO: 实现订单状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 撤销订单
+     */
+    @PostMapping("/order/confirmOrder")
+    public R<String> confirmOrder(@RequestBody ThirdpartyConfirmOrderBo bo) {
+        // TODO: 实现撤销订单逻辑
+        return R.ok();
+    }
+
+    /**
+     * 订单支付状态查询
+     */
+    @PostMapping("/order/getOrderPayState")
+    public R<ThirdpartyOrderPayStateDto> getOrderPayState(@RequestBody ThirdpartyOrderStatusBo bo) {
+        // TODO: 实现订单支付状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 订单支付状态写入
+     */
+    @PostMapping("/Order/setOrderPayState")
+    public R<String> setOrderPayState(@RequestBody ThirdpartySetOrderPayStateBo bo) {
+        // TODO: 实现订单支付状态写入逻辑
+        return R.ok();
+    }
+
+    /**
+     * 售后订单新增
+     */
+    @PostMapping("/AfterOrder/addAfterOrder")
+    public R<String> addAfterOrder(@RequestBody ThirdpartyAfterOrderAddBo bo) {
+        // TODO: 实现售后订单新增逻辑
+        return R.ok("新增成功");
+    }
+
+    /**
+     * 售后订单状态查询
+     */
+    @PostMapping("/AfterOrder/getAfterStatus")
+    public R<ThirdpartyAfterOrderStatusDto> getAfterStatus(@RequestBody ThirdpartyAfterOrderBo bo) {
+        // TODO: 实现售后订单状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 售后订单状态修改
+     */
+    @PostMapping("/AfterOrder/setAfterState")
+    public R<String> setAfterState(@RequestBody ThirdpartySetAfterStateBo bo) {
+        // TODO: 实现售后订单状态修改逻辑
+        return R.ok();
+    }
+
+    /**
+     * 售后订单列表查询
+     */
+    @PostMapping("/AfterOrder/getAfterOrderList")
+    public TableDataInfo<ThirdpartyAfterOrderDto> getAfterOrderList(@RequestBody ThirdpartyAfterOrderListBo bo, PageQuery pageQuery) {
+        // TODO: 实现售后订单列表查询逻辑
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 售后订单查询
+     */
+    @PostMapping("/AfterOrder/getAfterOrder")
+    public R<ThirdpartyAfterOrderDto> getAfterOrder(@RequestBody ThirdpartyAfterOrderBo bo) {
+        // TODO: 实现售后订单查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 物流查询
+     */
+    @PostMapping("/Other/geTtracking")
+    public R<ThirdpartyTrackingDto> geTtracking(@RequestBody ThirdpartyTrackingBo bo) {
+        // TODO: 实现物流查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 物流状态查询
+     */
+    @PostMapping("/Other/getTrackingStatus")
+    public R<ThirdpartyTrackingStatusDto> getTrackingStatus(@RequestBody ThirdpartyTrackingStatusBo bo) {
+        // TODO: 实现物流状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 对账列表查询
+     */
+    @PostMapping("/Other/getReconList")
+    public TableDataInfo<ThirdpartyReconDto> getReconList(@RequestBody ThirdpartyReconListBo bo, PageQuery pageQuery) {
+        // TODO: 实现对账列表查询逻辑
+        return TableDataInfo.build();
+    }
+
+    /**
+     * 对账申请
+     */
+    @PostMapping("/Other/applyRecon")
+    public R<String> applyRecon(@RequestBody ThirdpartyApplyReconBo bo) {
+        // TODO: 实现对账申请逻辑
+        return R.ok();
+    }
+
+    /**
+     * 对账状态查询
+     */
+    @PostMapping("/Other/getReconState")
+    public R<ThirdpartyReconStateDto> getReconState(@RequestBody ThirdpartyReconStateBo bo) {
+        // TODO: 实现对账状态查询逻辑
+        return R.ok();
+    }
+
+    /**
+     * 申请开票
+     */
+    @PostMapping("/Other/orderInvoice")
+    public R<String> orderInvoice(@RequestBody ThirdpartyOrderInvoiceBo bo) {
+        // TODO: 实现申请开票逻辑
+        return R.ok();
+    }
+
+    /**
+     * 开票信息查询
+     */
+    @PostMapping("/Other/getOrderInvoice")
+    public R<ThirdpartyOrderInvoiceDto> getOrderInvoice(@RequestBody ThirdpartyOrderInvoiceBo bo) {
+        // TODO: 实现开票信息查询逻辑
+        return R.ok();
+    }
+}

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

@@ -374,6 +374,7 @@ public class ZhongChePullController {
     @PostMapping("/egoods/import")
     public GoodsImportVo egoodsImport(@RequestBody GoodsImportBo bo) throws ZhongcheException {
         ZCR responseDto = doZcPost("/api/egoods/import", bo);
+        log.info(JSONUtil.toJsonStr(bo));
         //解析业务响应参数
         GoodsImportVo zcr = parseZcResponse(responseDto, GoodsImportVo.class);
         return zcr;
@@ -409,7 +410,9 @@ public class ZhongChePullController {
     @PostMapping("/egoods/price/update")
     public GoodsPriceUpdateVo egoodsPriceUpdate(@RequestBody GoodsImportBo bo) {
         ZCR responseDto = doZcPost("/api/egoods/price/update", bo);
+        log.info("商品价格变更参数:{}",JSONUtil.toJsonStr(bo));
         GoodsPriceUpdateVo zcr = parseZcResponse(responseDto, GoodsPriceUpdateVo.class);
+        log.info("商品价格变更结果:{}", zcr);
         return zcr;
     }
 
@@ -418,7 +421,9 @@ public class ZhongChePullController {
     public GoodsStatusUpdateVo egoodsStatusUpdate(@RequestBody GoodsStatusUpdateBo bo) {
 
         ZCR responseDto = doZcPost("/api/egoods/status/update", bo);
+        log.info("商品上下架状态变更参数:{}",JSONUtil.toJsonStr(bo));
         GoodsStatusUpdateVo zcr = parseZcResponse(responseDto, GoodsStatusUpdateVo.class);
+        log.info("商品上下架状态变更结果:{}", zcr);
         return zcr;
     }
 
@@ -426,7 +431,9 @@ public class ZhongChePullController {
     @PostMapping("/egoods/imgs/update")
     public GoodsImageUpdateVo egoodsImgsUpdate(@RequestBody GoodsImageUpdateBo bo) {
         ZCR responseDto = doZcPost("/api/egoods/imgs/update", bo);
+        log.info("商品图片变更参数:{}",JSONUtil.toJsonStr(bo));
         GoodsImageUpdateVo zcr = parseZcResponse(responseDto, GoodsImageUpdateVo.class);
+        log.info("商品图片变更结果:{}", zcr);
         return zcr;
     }
 
@@ -434,7 +441,9 @@ public class ZhongChePullController {
     @PostMapping("/egoods/properties/update")
     public GoodsUpdateVo egoodsPropertiesUpdate(@RequestBody GoodsPropertiesUpdateBo bo) {
         ZCR responseDto = doZcPost("/api/egoods/properties/update", bo);
+        log.info("商品规格信息变更参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("商品规格信息变更结果:{}", zcr);
         return zcr;
     }
 
@@ -442,7 +451,9 @@ public class ZhongChePullController {
     @PostMapping("/egoods/detail/update")
     public GoodsUpdateVo egoodsDetailUpdate(@RequestBody GoodsDetailBo bo) {
         ZCR responseDto = doZcPost("/api/egoods/detail/update", bo);
+        log.info("商品详情信息变更参数:{}",JSONUtil.toJsonStr(bo));
         GoodsUpdateVo zcr = parseZcResponse(responseDto, GoodsUpdateVo.class);
+        log.info("商品详情信息变更结果:{}", zcr);
         return zcr;
     }
 

+ 31 - 13
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongche/ZhongChePushController.java

@@ -6,10 +6,12 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.domain.R;
 import org.dromara.common.core.domain.zhongche.domain.Goods;
 import org.dromara.common.core.domain.zhongche.domain.Prices;
 import org.dromara.common.core.domain.zhongche.vo.OrderDetailVo;
@@ -23,8 +25,10 @@ import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.api.zhongche.domain.Catalog;
 import org.dromara.external.controller.zhongche.handle.MallMessageDispatcher;
+import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.service.IExternalProductCategoryService;
+import org.dromara.external.service.IExternalProductService;
 import org.dromara.external.util.SM2SignatureUtils;
 import org.dromara.external.util.SignParamUtils;
 import org.dromara.product.api.RemoteExternalOrderService;
@@ -34,10 +38,7 @@ import org.dromara.product.api.domain.zhongche.dto.StocksResult;
 import org.dromara.product.api.domain.zhongche.dto.StocksResultDto;
 import org.springframework.beans.BeanUtils;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
@@ -70,6 +71,8 @@ public class ZhongChePushController {
 
     private final IExternalProductCategoryService externalProductCategoryService;
 
+    private final IExternalProductService externalProductService;
+
     //电商私钥
     private final static String DEVELOPER_PRIVATE_KEY = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgQu0H97EPqkgz1YS5LkzZNmkG3mS5Er8rJ2LSoJtuOlGgCgYIKoEcz1UBgi2hRANCAARP6NYwTHpW2QTL8A2f2hpgunEpDVkJBhErBQPLqNS/Si5Q+9I9wUpCYdk1EvB5Hw6yzkE4bYk5IZM1j+/SnNFn";
     //企采公钥
@@ -349,7 +352,7 @@ public class ZhongChePushController {
     /**
      * 核心业务:查询商品价格,映射文档返回格式
      */
-    private PricesVo queryGoodsPrice(List<String> goodsIdList) {
+    public PricesVo queryGoodsPrice(List<String> goodsIdList) {
         // 1. 初始化响应结果
         PricesVo pricesVo = new PricesVo();
         pricesVo.setPrices(new ArrayList<>());
@@ -370,8 +373,8 @@ public class ZhongChePushController {
                 priceResp.setDsPrice(new BigDecimal(-1));
                 priceResp.setPrice(new BigDecimal(-1));
                 priceResp.setTaxFreePrice(null);
-                priceResp.setTax(null);
-                priceResp.setTaxCode("");
+                priceResp.setTax(BigDecimal.valueOf(0.13));
+                priceResp.setTaxCode("107022301");
                 pricesVo.getPrices().add(priceResp);
                 continue;
             }
@@ -382,19 +385,34 @@ public class ZhongChePushController {
             priceResp.setDsPrice(dsPrice); // 保留2位小数,四舍五入
 
             // 协议价格(price)
-            BigDecimal protocolPrice = productPrice.getPrice() == null ? new BigDecimal(-1) : productPrice.getPrice();
-            priceResp.setPrice(protocolPrice);
+            ExternalProduct one = externalProductService.getOne(new LambdaQueryWrapper<>(ExternalProduct.class)
+                .eq(ExternalProduct::getProductNo, goodsId)
+                .last("LIMIT 1")
+            );
+            if (one == null) {
+                // 未找到协议价格,使用 Dubbo 返回的价格
+                BigDecimal protocolPrice = productPrice.getPrice() == null ? new BigDecimal(-1) : productPrice.getPrice();
+                priceResp.setPrice(protocolPrice);
+            } else {
+                // 找到协议价格,使用数据库中的协议价格
+                priceResp.setPrice(one.getExternalPrice());
+            }
             priceResp.setTaxFreePrice(null);
-            priceResp.setTax(productPrice.getTax());
+            priceResp.setTax(BigDecimal.valueOf(0.13));
             // 税收编码(非必填)
-            priceResp.setTaxCode(null);
-
+            priceResp.setTaxCode("107022301");
             // 3.3 添加到响应列表
             pricesVo.getPrices().add(priceResp);
         }
-
         return pricesVo;
     }
+    @GetMapping("/get/queryGoodsPrice")
+    public R getMallOrderNo() {
+
+        PricesVo pricesVo = queryGoodsPrice(List.of("002171604"));
+        return R.ok(pricesVo);
+    }
+
 
     // 4.5查询物流信息(物流信息尚未实现)
     @PostMapping("/get/track")

+ 48 - 48
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongzhi/ZhongZhiPullController.java

@@ -10,8 +10,8 @@ import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.external.api.zhongzhi.domain.ZZResult;
 import org.dromara.external.controller.ExternalItemController;
-import org.dromara.external.api.zhongzhi.domain.Result;
 import org.dromara.external.domain.ExternalProductBrand;
 import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.service.IExternalProductBrandService;
@@ -87,12 +87,12 @@ public class ZhongZhiPullController {
                 .form("timestamp", timestamp)
                 .form("sign", sign);
         String body = post.execute().body();
-        Result<Map<String,String>> result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            throw new RuntimeException(result.getDesc());
+        ZZResult<Map<String,String>> ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            throw new RuntimeException(ZZResult.getDesc());
         }
-        accessToken = result.getResult().get("access_token");
-        String expiresAt = result.getResult().get("expires_at");
+        accessToken = ZZResult.getResult().get("access_token");
+        String expiresAt = ZZResult.getResult().get("expires_at");
         long expiresIn = DateUtil.between(DateUtil.date(), DateUtil.parse(expiresAt), DateUnit.SECOND);
         RedisUtils.setCacheObject(key, accessToken, Duration.ofSeconds(expiresIn));
         return accessToken;
@@ -102,34 +102,34 @@ public class ZhongZhiPullController {
     * 获取平台信息接口
     * */
     @PostMapping("/gyssc/platform/info")
-    public Result getPlatformInfo() {
+    public ZZResult getPlatformInfo() {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/info");
         String accessToken = this.getAccessToken();
         post.form("token", accessToken);
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
 
     /**
     * 获取平台品目信息接口
     * */
     @PostMapping("/gyssc/platform/catalogs")
-    public Result getPlatformCatalogs() {
+    public ZZResult getPlatformCatalogs() {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/catalogs");
         String accessToken = this.getAccessToken();
         post.form("token", accessToken);
         post.form("platformCode", code);
         HashMap<String, String> stringStringHashMap = new HashMap<>();
         String body = post.execute().body();
-        Result<List<Map<String,String>>> result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult<List<Map<String,String>>> ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        result.getResult().forEach(map->{
+        ZZResult.getResult().forEach(map->{
 
             boolean exists = externalProductCategoryService.exists(Wrappers.lambdaQuery(ExternalProductCategory.class)
                 .eq(ExternalProductCategory::getCategoryNo, map.get("interfaceCode")));
@@ -147,52 +147,52 @@ public class ZhongZhiPullController {
             }
 
         });
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
     /**
      * 获取商品承诺/产品认证信息/七天无理由退货接口
      * */
     @PostMapping("/gyssc/platform/getRegionPromise")
-    public Result getRegionPromise(String access_token) {
+    public ZZResult getRegionPromise(String access_token) {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/getRegionPromise");
         post.header("Authorization", "Bearer " + access_token);
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
 
     /**
     * 获取标准品目标准参数项信息接口
     * */
     @PostMapping("/gyssc/platform/catalogsParam")
-    public Result getStandardCatalogs(String access_token) {
+    public ZZResult getStandardCatalogs(String access_token) {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/catalogsParam");
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
 
     /**
     * 获取品牌信息接口
     * */
     @PostMapping("/gyssc/platform/brands")
-    public Result getBrands() {
+    public ZZResult getBrands() {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/brands");
         String accessToken = this.getAccessToken();
         post.form("token", accessToken);
         post.form("platformCode", code);
         String body = post.execute().body();
-        Result<Map<String,String>> result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult<Map<String,String>> ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        result.getResult().forEach((k,v)->{
+        ZZResult.getResult().forEach((k, v)->{
             boolean exists = externalProductBrandService.exists(Wrappers.lambdaQuery(ExternalProductBrand.class)
                 .eq(ExternalProductBrand::getBrandNo, k));
                 ExternalProductBrand externalProductBrand = new ExternalProductBrand();
@@ -206,48 +206,48 @@ public class ZhongZhiPullController {
                         .eq(ExternalProductBrand::getBrandNo, k));
                 }
         });
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
     /**
     * 获取大数据链接接口
     * */
     @PostMapping("/gyssc/platform/getBigdataUrl")
-    public Result getBigdataUrl(String access_token) {
+    public ZZResult getBigdataUrl(String access_token) {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/getBigdataUrl");
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
     /**
     * 日志查询接口
     * */
     @PostMapping("/gyssc/platform/getPushLog")
-    public Result getPushLog(String access_token) {
+    public ZZResult getPushLog(String access_token) {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/getPushLog");
 
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
 
     /**
     * 价格来源选项接口
     * */
     @PostMapping("/gyssc/platform/goodsPriceSource")
-    public Result getGoodsPriceSource(String access_token) {
+    public ZZResult getGoodsPriceSource(String access_token) {
         HttpRequest post = HttpUtil.createPost(url + "gyssc/platform/goodsPriceSource");
         String body = post.execute().body();
-        Result result = JSONUtil.toBean(body, Result.class);
-        if (!result.getSuccess()) {
-            return Result.fail(result.getCode(), result.getDesc());
+        ZZResult ZZResult = JSONUtil.toBean(body, ZZResult.class);
+        if (!ZZResult.getSuccess()) {
+            return ZZResult.fail(ZZResult.getCode(), ZZResult.getDesc());
         }
-        return Result.ok(result.getResult());
+        return ZZResult.ok(ZZResult.getResult());
     }
 
 }

+ 107 - 107
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/controller/zhongzhi/ZhongZhiPushController.java

@@ -10,7 +10,7 @@ import lombok.RequiredArgsConstructor;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.json.utils.JsonUtils;
 import org.dromara.external.api.zhongzhi.domain.Attribute;
-import org.dromara.external.api.zhongzhi.domain.Result;
+import org.dromara.external.api.zhongzhi.domain.ZZResult;
 import org.dromara.external.api.zhongzhi.domain.bo.*;
 import org.dromara.external.api.zhongzhi.domain.vo.*;
 import org.dromara.external.domain.ExternalProductCategory;
@@ -44,7 +44,7 @@ import java.util.List;
 public class ZhongZhiPushController {
 
 
-    @DubboReference
+    @DubboReference(timeout = 30000)
     private final RemoteProductService remoteProductService;
 
     @DubboReference
@@ -57,15 +57,15 @@ public class ZhongZhiPushController {
     /**
      * 校验token
      * */
-    private Result checkToken(String token,String platformCode){
+    private ZZResult checkToken(String token, String platformCode){
         if(ObjectUtil.isEmpty(token)){
-            return Result.fail(5006,"token不能为空");
+            return ZZResult.fail(5006,"token不能为空");
         }
         if(StpUtil.getTokenTimeout(token) == -2l){
-            return Result.fail(5005,"token_expired");
+            return ZZResult.fail(5005,"token_expired");
         }
         if(ObjectUtil.isEmpty(platformCode)){
-            return Result.fail(5006,"平台标识不能为空");
+            return ZZResult.fail(5006,"平台标识不能为空");
         }
         return null;
     }
@@ -74,13 +74,13 @@ public class ZhongZhiPushController {
     * 获取电商商品变动消息
     * */
     @PostMapping("/product/getMessagePool")
-    public Result<List<ProductMessageInfo>> getMessagePool(GetMessagePoolBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<List<ProductMessageInfo>> getMessagePool(GetMessagePoolBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getType())){
-            return Result.fail(5006,"消息类型不能为空");
+            return ZZResult.fail(5006,"消息类型不能为空");
         }
         List<ProductChangeLogApiVo> productChangeLogs = remoteProductService.getProductChangeLogs(null, String.valueOf(bo.getType()));
         List<ProductMessageInfo> productMessageInfos = productChangeLogs.stream().map(productChangeLogVo -> {
@@ -97,19 +97,19 @@ public class ZhongZhiPushController {
             return productMessageInfo;
         }).toList();
 
-        return Result.ok(productMessageInfos);
+        return ZZResult.ok(productMessageInfos);
     }
     /**
     * 获取商品详情 362031
     * */
     @PostMapping("/product/detail_standard")
-    public Result<ZhongzhiExternalProductVo> detailStandard(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<ZhongzhiExternalProductVo> detailStandard(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
 
         ProductVo productDetail = remoteProductService.getProductDetail(Long.valueOf(bo.getSku()));
@@ -130,13 +130,13 @@ public class ZhongZhiPushController {
             .sku(String.valueOf(productDetail.getId()))
             .url(productDetail.getProductImage())
             .model(productDetail.getItemName())
-            .weight(productDetail.getWeight())
-            .image_path(productDetail.getProductImageUrl())
+            .weight(productDetail.getProductWeight())
+            .image_path(productDetail.getProductImage())
             .state(String.valueOf(productDetail.getProductStatus()))
             .brand_name(productDetail.getBrandName())
             .name(productDetail.getItemName())
             .product_area(null)
-            .upc(productDetail.getUpcBarcode())
+            .upc(productDetail.getBarCoding())
             .unit(productDetail.getUnitName())
             .category(null)
             .service(productDetail.getAfterSalesService())
@@ -147,52 +147,52 @@ public class ZhongZhiPushController {
             externalProductVo.setCategory(one.getCategoryNo());
         }
 
-        return Result.ok(externalProductVo);
+        return ZZResult.ok(externalProductVo);
     }
 
     /**
     * 获取商品参数信息
     * */
     @PostMapping("/product/product_attributes_standard")
-    public Result<Attribute> productAttributesStandard(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<Attribute> productAttributesStandard(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
         Attribute attribute = new Attribute();
-        return Result.ok(attribute);
+        return ZZResult.ok(attribute);
     }
 
     /**
     * 获取商品承诺函/产品认证信息/七天无理由退货(由电商提供)
     * */
     @PostMapping("/product/product_promise")
-    public Result<List<ProductPromiseVo>> productPromise(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<List<ProductPromiseVo>> productPromise(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
         List<ProductPromiseVo> productPromises = new ArrayList<>();
-        return Result.ok(productPromises);
+        return ZZResult.ok(productPromises);
     }
 
     /**
     * 商品上下架状态接口
     * */
     @PostMapping("/product/shelf_states")
-    public Result<List<ProductShelfStateVo>> shelfStates(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<List<ProductShelfStateVo>> shelfStates(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
         String[] skuIds = bo.getSku().split(",");
         List<ProductShelfStateVo> shelfState = new ArrayList<>();
@@ -203,22 +203,22 @@ public class ZhongZhiPushController {
             productShelfStateVo.setState(String.valueOf(productVo.getProductStatus()));
             shelfState.add(productShelfStateVo);
         }
-        return Result.ok(shelfState);
+        return ZZResult.ok(shelfState);
     }
 
     /**
     * 商品图片
     * */
     @PostMapping("/product/images")
-    public Result<List<ProductImageVo>> images(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<List<ProductImageVo>> images(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
-        List<ProductVo> productDetails = remoteProductService.getProductDetails(bo.getSku());
+        List<ProductVo> productDetails = remoteProductService.getProductDetailsByNo(bo.getSku());
         List<ProductImageVo> imageVos = productDetails.stream().map(productVo -> {
             ProductImageVo productImageVo = new ProductImageVo();
             productImageVo.setSku(String.valueOf(productVo.getId()));
@@ -235,21 +235,21 @@ public class ZhongZhiPushController {
             }
             return productImageVo;
         }).toList();
-        return Result.ok(imageVos);
+        return ZZResult.ok(imageVos);
     }
     /**
     * 商品价格接口
     * */
     @PostMapping("/product/prices")
-    public Result<List<ProductPriceVo>> prices(GetProductDetailBo bo) {
-        Result result = checkToken(bo.getToken(), bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<List<ProductPriceVo>> prices(GetProductDetailBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(), bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
-        List<ProductVo> productDetails = remoteProductService.getProductDetails(bo.getSku());
+        List<ProductVo> productDetails = remoteProductService.getProductDetailsByNo(bo.getSku());
         List<ProductPriceVo> prices = productDetails.stream().map(productVo -> {
             ProductPriceVo productPriceVo = new ProductPriceVo();
             productPriceVo.setSku(String.valueOf(productVo.getId()));
@@ -258,103 +258,103 @@ public class ZhongZhiPushController {
             productPriceVo.setStock(String.valueOf(productVo.getTotalInventory()));
             return productPriceVo;
         }).toList();
-        return Result.ok(prices);
+        return ZZResult.ok(prices);
     }
 
     /**
     * 删除消息接口
     * */
     @PostMapping("/product/delMessagePool")
-    public Result delMessagePool(DelMessagePoolBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult delMessagePool(DelMessagePoolBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getMessageId())){
-            return Result.fail(5006,"消息编号不能为空");
+            return ZZResult.fail(5006,"消息编号不能为空");
         }
         remoteProductService.delMessagePool(Long.valueOf(bo.getMessageId()));
-        return Result.ok("消息"+bo.getMessageId()+"删除成功", null);
+        return ZZResult.ok("消息"+bo.getMessageId()+"删除成功", null);
     }
 
     /**
     * 推送订单
     * */
     @PostMapping("/order/pushOrder")
-    public Result<OrderPushVo> pushOrder(OrderPushBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult<OrderPushVo> pushOrder(OrderPushBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         //校验必填字段
         if(ObjectUtil.isEmpty(bo.getYggc_order())){
-            return Result.fail(5006,"订单编号不能为空");
+            return ZZResult.fail(5006,"订单编号不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"订单商品不能为空");
+            return ZZResult.fail(5006,"订单商品不能为空");
         }
         List<OrderPushBo.SkuItem> sku = JsonUtils.parseArray(bo.getSku(), OrderPushBo.SkuItem.class);
         if(ObjectUtil.isEmpty(bo.getName())){
-            return Result.fail(5006,"收货人名称不能为空");
+            return ZZResult.fail(5006,"收货人名称不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getProvince())){
-            return Result.fail(5006,"一级地址不能为空");
+            return ZZResult.fail(5006,"一级地址不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getCity())){
-            return Result.fail(5006,"二级地址不能为空");
+            return ZZResult.fail(5006,"二级地址不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getCounty())){
-            return Result.fail(5006,"三级地址不能为空");
+            return ZZResult.fail(5006,"三级地址不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getAddress())){
-            return Result.fail(5006,"详细地址不能为空");
+            return ZZResult.fail(5006,"详细地址不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getZip())){
-            return Result.fail(5006,"邮编不能为空");
+            return ZZResult.fail(5006,"邮编不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getPhone()) && ObjectUtil.isEmpty(bo.getMobile())){
-            return Result.fail(5006,"手机号或座机号不能为空");
+            return ZZResult.fail(5006,"手机号或座机号不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getInvoice_title())){
-            return Result.fail(5006,"发票抬头不能为空");
+            return ZZResult.fail(5006,"发票抬头不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getInvoice_org_code())){
-            return Result.fail(5006,"纳税人识别号不能为空");
+            return ZZResult.fail(5006,"纳税人识别号不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getInvoice_type())){
-            return Result.fail(5006,"发票类型不能为空");
+            return ZZResult.fail(5006,"发票类型不能为空");
         }else if(bo.getInvoice_type().equals("2")){
             if(ObjectUtil.isEmpty(bo.getInvoice_name())){
-                return Result.fail(5006,"增值税发票抬头不能为空");
+                return ZZResult.fail(5006,"增值税发票抬头不能为空");
             }
             if(ObjectUtil.isEmpty(bo.getInvoice_phone())){
-                return Result.fail(5006,"发票电话不能为空");
+                return ZZResult.fail(5006,"发票电话不能为空");
             }
             if(ObjectUtil.isEmpty(bo.getInvoice_bank())){
-                return Result.fail(5006,"发票开户银行不能为空");
+                return ZZResult.fail(5006,"发票开户银行不能为空");
             }
             if(ObjectUtil.isEmpty(bo.getInvoice_bank_code())){
-                return Result.fail(5006,"发票开户行账号不能为空");
+                return ZZResult.fail(5006,"发票开户行账号不能为空");
             }
             if(ObjectUtil.isEmpty(bo.getInvoice_address())){
-                return Result.fail(5006,"注册地址不能为空");
+                return ZZResult.fail(5006,"注册地址不能为空");
             }
         }
 
         if(ObjectUtil.isEmpty(bo.getPayment())){
-            return Result.fail(5006,"付款方式不能为空");
+            return ZZResult.fail(5006,"付款方式不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getOrder_price())){
-            return Result.fail(5006,"订单金额不能为空");
+            return ZZResult.fail(5006,"订单金额不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getFreight())){
-            return Result.fail(5006,"运费不能为空");
+            return ZZResult.fail(5006,"运费不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getMode())){
-            return Result.fail(5006,"订单模式不能为空");
+            return ZZResult.fail(5006,"订单模式不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getOrderCode())){
-            return Result.fail(5006,"卖场订单编号不能为空");
+            return ZZResult.fail(5006,"卖场订单编号不能为空");
         }
         OrderPushDto dto = BeanUtil.toBean(bo, OrderPushDto.class);
 //        remoteOrderService.pushOrder(dto);
@@ -373,64 +373,64 @@ public class ZhongZhiPushController {
 //        sku.setNum(bo.get);
 //        orderPushVo.setSku();
 
-        return Result.ok(orderPushVo);
+        return ZZResult.ok(orderPushVo);
     }
 
     /**
     * 确认接收订单
     * */
     @PostMapping("/order/confirm")
-    public Result confirm(OrderPushBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult confirm(OrderPushBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getOrder_id())){
-            return Result.fail(5006,"订单编号不能为空");
+            return ZZResult.fail(5006,"订单编号不能为空");
         }
 //        remoteOrderService.confirmOrder(Long.valueOf(bo.getOrder_id()));
-        return Result.ok("成功确认接收订单",null);
+        return ZZResult.ok("成功确认接收订单",null);
     }
 
     /**
     * 订单状态通知接口
     * */
     @PostMapping("/order/notice")
-    public Result notice(OrderNoticeBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult notice(OrderNoticeBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getOrderId())){
-            return Result.fail(5006,"订单编号不能为空");
+            return ZZResult.fail(5006,"订单编号不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getOrderState())){
-            return Result.fail(5006,"订单状态不能为空");
+            return ZZResult.fail(5006,"订单状态不能为空");
         }
         OrderNoticeDto dto = BeanUtil.toBean(bo, OrderNoticeDto.class);
 //        remoteOrderService.notice(dto);
-        return Result.ok("成功收到通知",null);
+        return ZZResult.ok("成功收到通知",null);
     }
 
     /**
     * 商品状态通知接口
     * */
     @PostMapping("/product/notice")
-    public Result notice(ProductNoticeBo bo) {
-        Result result = checkToken(bo.getToken(),bo.getPlatformCode());
-        if(ObjectUtil.isNotEmpty(result)){
-            return result;
+    public ZZResult notice(ProductNoticeBo bo) {
+        ZZResult ZZResult = checkToken(bo.getToken(),bo.getPlatformCode());
+        if(ObjectUtil.isNotEmpty(ZZResult)){
+            return ZZResult;
         }
         if(ObjectUtil.isEmpty(bo.getSku())){
-            return Result.fail(5006,"商品编号不能为空");
+            return ZZResult.fail(5006,"商品编号不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getStatus())){
-            return Result.fail(5006,"商品状态不能为空");
+            return ZZResult.fail(5006,"商品状态不能为空");
         }
         if(ObjectUtil.isEmpty(bo.getMessage())){
-            return Result.fail(5006,"商品状态通知不能为空");
+            return ZZResult.fail(5006,"商品状态通知不能为空");
         }
-        return Result.ok("成功收到通知",null);
+        return ZZResult.ok("成功收到通知",null);
     }
 
 

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/ExternalProduct.java

@@ -110,7 +110,7 @@ public class ExternalProduct extends TenantEntity {
     /**
      * 起订量
      * */
-    private Integer minOrderQuantity;
+    private Long minOrderQuantity;
 
     /**
      * 计价规则(0 一品一价,1 按类目折扣率报价)

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/bo/ExternalProductBo.java

@@ -101,7 +101,7 @@ public class ExternalProductBo extends BaseEntity {
     /**
     * 起订量
     * */
-    private Integer minOrderQuantity;
+    private Long minOrderQuantity;
 
     /**
      * 计价规则(0 一品一价,1 按类目折扣率报价)

+ 1 - 1
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductImportVo.java

@@ -73,7 +73,7 @@ public class ExternalProductImportVo implements Serializable {
      * 起订量
      */
     @ExcelProperty(value = "起订量", index = 8)
-    private Integer minOrderQuantity;
+    private Long minOrderQuantity;
 
     /**
      * 上架状态(0 上架,1 下架)

+ 113 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/domain/vo/ExternalProductNewImportVo.java

@@ -0,0 +1,113 @@
+package org.dromara.external.domain.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 外部商品导入视图对象(新模板)
+ *
+ * @author LionLi
+ * @date 2026-04-02
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class ExternalProductNewImportVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 序号
+     */
+    @ExcelProperty(value = "序号", index = 0)
+    private Integer serialNumber;
+
+    /**
+     * 项目编号
+     */
+    @ExcelProperty(value = "项目编号", index = 1)
+    private String itemNo;
+
+    /**
+     * 产品编号
+     */
+    @ExcelProperty(value = "产品编号", index = 2)
+    private String productNo;
+
+    /**
+     * 产品名称
+     */
+    @ExcelProperty(value = "产品名称", index = 3)
+    private String productName;
+
+    /**
+     * 商品说明
+     */
+    @ExcelProperty(value = "商品说明", index = 4)
+    private String productDescription;
+
+    /**
+     * 69 码 (多个、隔离)
+     */
+    @ExcelProperty(value = "69 码 (多个、隔离)", index = 5)
+    private String barcode69;
+
+    /**
+     * 规格型号
+     */
+    @ExcelProperty(value = "规格型号", index = 6)
+    private String specificationModel;
+
+    /**
+     * 保质期
+     */
+    @ExcelProperty(value = "保质期", index = 7)
+    private String shelfLife;
+
+    /**
+     * 属性 (至少一个)
+     */
+    @ExcelProperty(value = "属性 (至少一个)", index = 8)
+    private String attributes;
+
+    /**
+     * 起订量
+     */
+    @ExcelProperty(value = "起订量", index = 9)
+    private Long minOrderQuantity;
+
+    /**
+     * 市场价
+     */
+    @ExcelProperty(value = "市场价", index = 10)
+    private BigDecimal marketPrice;
+
+    /**
+     * 官网价
+     */
+    @ExcelProperty(value = "官网价", index = 11)
+    private BigDecimal officialPrice;
+
+    /**
+     * 协议价 (中车)
+     */
+    @ExcelProperty(value = "协议价 (中车)", index = 12)
+    private BigDecimal agreementPrice;
+
+    /**
+     * 比价链接 (多个、隔离)
+     */
+    @ExcelProperty(value = "比价链接 (多个、隔离)", index = 13)
+    private String priceComparisonLink;
+
+    /**
+     * 链接价
+     */
+    @ExcelProperty(value = "链接价", index = 14)
+    private BigDecimal linkPrice;
+}

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

@@ -64,6 +64,8 @@ public class ExternalProductVo implements Serializable {
     @ExcelProperty(value = "外部分类id")
     private Long externalCategoryId;
 
+    private String externalCategoryNo;
+
     /**
      * 第三方品目名称
      */
@@ -216,8 +218,6 @@ public class ExternalProductVo implements Serializable {
      */
     private java.math.BigDecimal purchasingPrice;
 
-
-
     /**
      * 暂估毛利率
      * */

+ 15 - 4
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/dubbo/RemoteExternalProductServiceImpl.java

@@ -15,6 +15,7 @@ import org.dromara.external.service.IExternalProductService;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * @author
@@ -80,11 +81,21 @@ public class RemoteExternalProductServiceImpl implements RemoteExternalProductSe
     public void syncExternalProduct(List<ExternalProductDto> products) {
         for (ExternalProductDto product : products) {
             //不存在则新增存在则跳过
-            if (!externalProductService.exists(Wrappers.lambdaQuery(ExternalProduct.class)
-                .eq(ExternalProduct::getProductId, product.getProductId()))){
-                ExternalProduct externalProduct = BeanUtil.toBean(product, ExternalProduct.class);
-                externalProductService.save(externalProduct);
+            if(Objects.equals(product.getType(),0)){
+                if (!externalProductService.exists(Wrappers.lambdaQuery(ExternalProduct.class)
+                    .eq(ExternalProduct::getProductId, product.getProductId()))){
+                    ExternalProduct externalProduct = BeanUtil.toBean(product, ExternalProduct.class);
+                    externalProductService.save(externalProduct);
+                }
+            }else {
+                externalProductService.update(
+                    Wrappers.lambdaUpdate(ExternalProduct.class)
+                        .set(ExternalProduct::getExternalPrice, product.getExternalPrice())
+                        .eq(ExternalProduct::getProductId, product.getProductId())
+                        .eq(ExternalProduct::getItemId, product.getItemId())
+                );
             }
+
         }
 
 

+ 7 - 5
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/ProductPushStrategy.java

@@ -3,6 +3,8 @@ package org.dromara.external.handler;
 import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.domain.ExternalProduct;
+import org.dromara.external.domain.vo.ExternalProductVo;
+import org.dromara.product.api.domain.ProductVo;
 
 import java.util.List;
 
@@ -16,25 +18,25 @@ public interface ProductPushStrategy {
     /**
      * 商品价格变更
      */
-    GoodsPriceUpdateVo updatePrice(Long itemId, GoodsImportBo bo);
+    GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products);
 
     /**
      * 商品上下架状态变更
      */
-    GoodsStatusUpdateVo updateStatus(Long itemId, GoodsStatusUpdateBo bo);
+    GoodsStatusUpdateVo updateStatus(List<String> productNos, Integer status);
 
     /**
      * 商品图片变更
      */
-    GoodsImageUpdateVo updateImages(Long itemId, GoodsImageUpdateBo bo);
+    GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products);
 
     /**
      * 商品规格信息变更
      */
-    GoodsUpdateVo updateProperties(Long itemId, GoodsPropertiesUpdateBo bo);
+    GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products);
 
     /**
      * 商品详情信息变更
      */
-    GoodsUpdateVo updateDetail(Long itemId, GoodsDetailBo bo);
+    GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products);
 }

+ 138 - 23
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongChePushStrategy.java

@@ -1,14 +1,19 @@
 package org.dromara.external.handler.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.exception.api.ZhongcheException;
 import org.dromara.common.core.utils.StringUtils;
+import org.dromara.external.api.zhongche.domain.GoodsImageUpdateItem;
 import org.dromara.external.api.zhongche.domain.GoodsImportItem;
+import org.dromara.external.api.zhongche.domain.GoodsPropertiesUpdateItem;
+import org.dromara.external.api.zhongche.domain.GoodsStatusUpdateItem;
 import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.controller.zhongche.ZhongChePullController;
@@ -28,13 +33,18 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.math.BigDecimal;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Component("zhongchePushStrategy")
 @RequiredArgsConstructor
+@Slf4j
 public class ZhongChePushStrategy implements ProductPushStrategy {
 
+    private final String username = "20240316001";
+
     @DubboReference
     private final RemoteProductService remoteProductService;
 
@@ -50,7 +60,6 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
 
     @Override
     public void push( Long itemId,List<ExternalProduct> products) {
-        String username = "20240316001";
         List<ExternalProductVo> productVoList = new ArrayList<>();
         for (ExternalProduct product : products) {
             ExternalProductVo vo = BeanUtil.toBean(product, ExternalProductVo.class);
@@ -62,6 +71,8 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
             BeanUtil.copyProperties(productDetail, item);
             item.setId(externalProductVo.getId());
             item.setProductStatus(externalProductVo.getProductStatus());
+            item.setMemberPrice(productDetail.getMemberPrice());
+            item.setProductImage(productDetail.getImageUrl());
         });
 
         // 收集所有 externalCategoryId
@@ -74,17 +85,19 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
                 externalProductCategoryService.listByIds(categoryIds);
 
             // 转成 Map <id, name>
-            Map<Long, String> categoryMap = categoryList.stream()
+            Map<Long, ExternalProductCategory> categoryMap = categoryList.stream()
                 .collect(Collectors.toMap(
                     ExternalProductCategory::getId,
-                    ExternalProductCategory::getCategoryName
+                    Function.identity()
+
                 ));
 
             // 回填分类名称
             productVoList.forEach(item -> {
-                String categoryName =
+                ExternalProductCategory externalProductCategory =
                     categoryMap.get(item.getExternalCategoryId());
-                item.setStandardCatalogName(categoryName);
+                item.setStandardCatalogName(externalProductCategory.getCategoryName());
+                item.setExternalCategoryNo(externalProductCategory.getCategoryNo());
             });
 
             List<Long> productIds = productVoList.stream()
@@ -113,10 +126,10 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
             List<GoodsImportItem> batchGoods = new ArrayList<>();
         productVoList.forEach(item -> {
             GoodsImportItem goodsImportItem = new GoodsImportItem();
-            goodsImportItem.setGoodsId(item.getProductId().toString());
+            goodsImportItem.setGoodsId(item.getProductNo());
             goodsImportItem.setCatalogId(item.getBottomCategoryId().toString());
             goodsImportItem.setCatalogName(item.getCategoryName());
-            goodsImportItem.setStandardCatalogId(item.getExternalCategoryId().toString());
+            goodsImportItem.setStandardCatalogId(item.getExternalCategoryNo());
             goodsImportItem.setStandardCatalogName(item.getStandardCatalogName());
             //这里有英文有中文混合,需要处理
             String brandName = item.getBrandName();
@@ -127,12 +140,16 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
             }
             goodsImportItem.setName(item.getItemName());
             goodsImportItem.setDsPrice(item.getMarketPrice());
-            goodsImportItem.setPrice(item.getMemberPrice());
+            goodsImportItem.setPrice(item.getExternalPrice());
             //第三方价格
             goodsImportItem.setThirdPrice(item.getExternalPrice());
             goodsImportItem.setUnit(item.getUnitName());
             //TODO 库存
-            goodsImportItem.setStock(productAggregateMap.get(item.getProductId()).getStock());
+//            goodsImportItem.setStock(productAggregateMap.get(item.getProductId()).getStock());
+            goodsImportItem.setStock(999);
+            //链接
+            goodsImportItem.setGoodsUrl(productAggregateMap.get(item.getProductId()).getGoodsUrl());
+            goodsImportItem.setThirdUrl(productAggregateMap.get(item.getProductId()).getThirdUrl());
             //图片
             String rawImageStr = item.getProductImage();
             List<String> imageList = new ArrayList<>();
@@ -154,21 +171,35 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
             goodsImportItem.setBarImgUrls(barImgUrlsJson);
             //TODO 商品描述
             goodsImportItem.setDescription(productAggregateMap.get(item.getProductId()).getDescription());
+
             //TODO 商品规格  默认 颜色:白色
-            goodsImportItem.setProperties("{\"颜色\":\"白色\"}");
+//            if (StringUtils.isNotBlank(productAggregateMap.get(item.getProductId()).getDiyAttributesList())) {
+//                String diyAttributesList = productAggregateMap.get(item.getProductId()).getDiyAttributesList();
+//                List<Map> list = JSONUtil.toList(diyAttributesList, Map.class);
+//                //格式为[{attributeKey:"",attributeValue:""}]转换成 [{key:value}]
+//                List<Map<String, String>> map = list.stream().map(e -> {
+//                    Map<String, String> result = new HashMap<>();
+//                    result.put(e.get("attributeKey").toString(), e.get("attributeValue").toString());
+//                    return result;
+//                }).collect(Collectors.toList());
+//                goodsImportItem.setProperties(JSONUtil.toJsonStr(map));
+//            }else{
+                goodsImportItem.setProperties("{\"保质期\":\"12个月\"}");
+//            }
+
             //TODO 是否自营
-            goodsImportItem.setIsSelfOperated(item.getIsSelf());
+            goodsImportItem.setIsSelfOperated(1);
             //税率
-            goodsImportItem.setTax(item.getTaxRate());
+            goodsImportItem.setTax( new BigDecimal("0.13"));
             //TODO 税收编码   默认填 1
-            goodsImportItem.setTaxCode("1");
-
+            goodsImportItem.setTaxCode("107022301");
             batchGoods.add(goodsImportItem);
         });
             GoodsImportBo bo = new GoodsImportBo();
             bo.setAccount(username);
             bo.setGoods(batchGoods);
             GoodsImportVo goodsImportVo = new GoodsImportVo();
+
             try {
                 goodsImportVo = zhongChePullController.egoodsImport(bo);
                 if (goodsImportVo.getResult() == 1) {
@@ -219,28 +250,112 @@ public class ZhongChePushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId, GoodsImportBo bo) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products) {
+        GoodsImportBo bo =  new GoodsImportBo();
+        bo.setAccount(username);
+//        bo.setGoods(products.stream().map(item ->{
+//            GoodsImportItem goodsImportItem = new GoodsImportItem();
+//            goodsImportItem.set
+//            return goodsImportItem;
+//        }).toList());
         return zhongChePullController.egoodsPriceUpdate(bo);
     }
 
     @Override
-    public GoodsStatusUpdateVo updateStatus(Long itemId, GoodsStatusUpdateBo bo) {
-        return zhongChePullController.egoodsStatusUpdate(bo);
+    public GoodsStatusUpdateVo updateStatus(List<String> productNos, Integer status) {
+        GoodsStatusUpdateBo goodsStatusUpdateBo = new GoodsStatusUpdateBo();
+        goodsStatusUpdateBo.setAccount(username);
+        goodsStatusUpdateBo.setGoods(productNos.stream().map(productNo -> {
+            GoodsStatusUpdateItem item = new GoodsStatusUpdateItem();
+            item.setGoodsId(productNo);
+            item.setStatus(status);
+            return item;
+        }).collect(Collectors.toList()));
+        return zhongChePullController.egoodsStatusUpdate(goodsStatusUpdateBo);
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId, GoodsImageUpdateBo bo) {
-        return zhongChePullController.egoodsImgsUpdate(bo);
+    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products) {
+        try {
+            GoodsImageUpdateBo bo = new GoodsImageUpdateBo();
+            bo.setAccount(username);
+            bo.setGoods(products.stream().map(item -> {
+                GoodsImageUpdateItem goodsImageUpdateItem = new GoodsImageUpdateItem();
+                goodsImageUpdateItem.setBarImgUrls(item.getImageUrl());
+                goodsImageUpdateItem.setGoodsId(item.getProductNo());
+                return goodsImageUpdateItem;
+            }).toList());
+            return zhongChePullController.egoodsImgsUpdate(bo);
+        }catch (ZhongcheException e){
+            for (ProductVo productVo : products) {
+                ExternalPushPoolLog externalPushPoolLog = new ExternalPushPoolLog();
+                externalPushPoolLog.setItemId(itemId);
+                externalPushPoolLog.setProductId(productVo.getId());
+                externalPushPoolLog.setPushStatus("1");
+                externalPushPoolLog.setReason(e.getMessage());
+                externalPushPoolLogService.save(externalPushPoolLog);
+            }
+            throw e;
+        }
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId, GoodsPropertiesUpdateBo bo) {
-        return zhongChePullController.egoodsPropertiesUpdate(bo);
+    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products) {
+        try {
+            GoodsPropertiesUpdateBo bo = new GoodsPropertiesUpdateBo();
+            bo.setAccount(username);
+            bo.setGoods(products.stream().map(item ->{
+                GoodsPropertiesUpdateItem goodsImageUpdateItem = new GoodsPropertiesUpdateItem();
+                goodsImageUpdateItem.setProperties("{\"保质期\":\"12个月\"}");
+                goodsImageUpdateItem.setGoodsId(item.getProductNo());
+                return goodsImageUpdateItem;
+            }).toList());
+            return zhongChePullController.egoodsPropertiesUpdate(bo);
+        }catch (ZhongcheException e){
+            for (ProductVo productVo : products) {
+                ExternalPushPoolLog externalPushPoolLog = new ExternalPushPoolLog();
+                externalPushPoolLog.setItemId(itemId);
+                externalPushPoolLog.setProductId(productVo.getId());
+                externalPushPoolLog.setPushStatus("1");
+                externalPushPoolLog.setReason(e.getMessage());
+                externalPushPoolLogService.save(externalPushPoolLog);
+            }
+            throw e;
+        }
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId, GoodsDetailBo bo) {
-        return zhongChePullController.egoodsDetailUpdate(bo);
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products) {
+        try {
+            GoodsDetailBo bo = new GoodsDetailBo();
+            bo.setAccount(username);
+            bo.setGoods(products.stream().map(item ->{
+                GoodsDetailUpdateBo goodsImageUpdateItem = new GoodsDetailUpdateBo();
+                goodsImageUpdateItem.setBrandName(item.getBrandName());
+                goodsImageUpdateItem.setDescription(item.getPcDetail());
+                goodsImageUpdateItem.setUpc(item.getBarCoding());
+                goodsImageUpdateItem.setMoq(BigDecimal.valueOf(item.getMinOrderQuantity()));
+                goodsImageUpdateItem.setIsSelfOperated(1);
+                goodsImageUpdateItem.setGoodsUrl(item.getReferenceLink());
+                goodsImageUpdateItem.setThirdUrl(item.getReferenceLink());
+                goodsImageUpdateItem.setTaxCode("107022301");
+                goodsImageUpdateItem.setTax(BigDecimal.valueOf(0.13));
+
+                goodsImageUpdateItem.setGoodsId(item.getProductNo());
+                return goodsImageUpdateItem;
+            }).toList());
+            return zhongChePullController.egoodsDetailUpdate(bo);
+        }catch (ZhongcheException e){
+            for (ProductVo productVo : products) {
+                ExternalPushPoolLog externalPushPoolLog = new ExternalPushPoolLog();
+                externalPushPoolLog.setItemId(itemId);
+                externalPushPoolLog.setProductId(productVo.getId());
+                externalPushPoolLog.setPushStatus("1");
+                externalPushPoolLog.setReason(e.getMessage());
+                externalPushPoolLogService.save(externalPushPoolLog);
+            }
+            throw e;
+        }
     }
 
     // --------------------- 核心判断方法 ---------------------

+ 6 - 5
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/handler/impl/ZhongZhiPushStrategy.java

@@ -4,6 +4,7 @@ import org.dromara.external.api.zhongche.domain.bo.*;
 import org.dromara.external.api.zhongche.domain.vo.*;
 import org.dromara.external.domain.ExternalProduct;
 import org.dromara.external.handler.ProductPushStrategy;
+import org.dromara.product.api.domain.ProductVo;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -21,31 +22,31 @@ public class ZhongZhiPushStrategy implements ProductPushStrategy {
     }
 
     @Override
-    public GoodsPriceUpdateVo updatePrice(Long itemId, GoodsImportBo bo) {
+    public GoodsPriceUpdateVo updatePrice(Long itemId,List<ProductVo> products) {
         // TODO: 实现中职平台价格更新逻辑
         return null;
     }
 
     @Override
-    public GoodsStatusUpdateVo updateStatus(Long itemId, GoodsStatusUpdateBo bo) {
+    public GoodsStatusUpdateVo updateStatus(List<String> productNos, Integer status) {
         // TODO: 实现中职平台状态更新逻辑
         return null;
     }
 
     @Override
-    public GoodsImageUpdateVo updateImages(Long itemId, GoodsImageUpdateBo bo) {
+    public GoodsImageUpdateVo updateImages(Long itemId,List<ProductVo> products) {
         // TODO: 实现中职平台图片更新逻辑
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateProperties(Long itemId, GoodsPropertiesUpdateBo bo) {
+    public GoodsUpdateVo updateProperties(Long itemId,List<ProductVo> products) {
         // TODO: 实现中职平台规格更新逻辑
         return null;
     }
 
     @Override
-    public GoodsUpdateVo updateDetail(Long itemId, GoodsDetailBo bo) {
+    public GoodsUpdateVo updateDetail(Long itemId,List<ProductVo> products) {
         // TODO: 实现中职平台详情更新逻辑
         return null;
     }

+ 10 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/listener/ExternalProductImportListener.java

@@ -50,9 +50,9 @@ public class ExternalProductImportListener extends AnalysisEventListener<Externa
         this.externalProductService = null;
     }
 
-    public ExternalProductImportListener(IExternalProductService externalProductService) {
+    public ExternalProductImportListener(IExternalProductService externalProductService,RemoteProductService remoteProductService) {
         this.externalProductService = externalProductService;
-        this.remoteProductService = SpringUtils.getBean(RemoteProductService.class);
+        this.remoteProductService = remoteProductService;
         this.externalItemService = SpringUtils.getBean(IExternalItemService.class);
         this.externalProductCategoryService = SpringUtils.getBean(IExternalProductCategoryService.class);
     }
@@ -122,6 +122,14 @@ public class ExternalProductImportListener extends AnalysisEventListener<Externa
                     categoryId = category.getId();
                     discountRate = category.getDiscountRate();
                 }
+            }else {
+                ExternalProductCategory category = externalProductCategoryService.getOne(
+                    Wrappers.<ExternalProductCategory>lambdaQuery()
+                        .eq(ExternalProductCategory::getCategoryNo, importVo.getCategoryNo())
+                );
+                if (ObjectUtil.isNotEmpty(category)) {
+                    categoryId = category.getId();
+                }
             }
 
             // 计算协议价:如果是按类目折扣率报价,则协议价 = 官网价 * 折扣率

+ 177 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/listener/ExternalProductNewImportListener.java

@@ -0,0 +1,177 @@
+package org.dromara.external.listener;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.idev.excel.context.AnalysisContext;
+import cn.idev.excel.event.AnalysisEventListener;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.exception.ServiceException;
+import org.dromara.common.core.utils.SpringUtils;
+import org.dromara.common.core.utils.StreamUtils;
+import org.dromara.common.core.utils.ValidatorUtils;
+import org.dromara.common.excel.core.ExcelListener;
+import org.dromara.common.excel.core.ExcelResult;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.external.domain.ExternalItem;
+import org.dromara.external.domain.ExternalProduct;
+import org.dromara.external.domain.ExternalProductCategory;
+import org.dromara.external.domain.bo.ExternalProductBo;
+import org.dromara.external.domain.vo.ExternalProductNewImportVo;
+import org.dromara.external.service.IExternalItemService;
+import org.dromara.external.service.IExternalProductCategoryService;
+import org.dromara.external.service.IExternalProductService;
+import org.dromara.product.api.RemoteProductService;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 外部商品导入监听器(新模板)
+ *
+ * @author LionLi
+ * @date 2026-04-02
+ */
+@Slf4j
+public class ExternalProductNewImportListener extends AnalysisEventListener<ExternalProductNewImportVo> implements ExcelListener<ExternalProductNewImportVo> {
+
+    private final IExternalProductService externalProductService;
+    private RemoteProductService remoteProductService;
+    private IExternalItemService externalItemService;
+    private IExternalProductCategoryService externalProductCategoryService;
+
+    private int successNum = 0;
+    private int failureNum = 0;
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+
+    public ExternalProductNewImportListener() {
+        this.externalProductService = null;
+    }
+
+    public ExternalProductNewImportListener(IExternalProductService externalProductService, RemoteProductService remoteProductService) {
+        this.externalProductService = externalProductService;
+        this.remoteProductService = remoteProductService;
+        this.externalItemService = SpringUtils.getBean(IExternalItemService.class);
+        this.externalProductCategoryService = SpringUtils.getBean(IExternalProductCategoryService.class);
+    }
+
+    @Override
+    public void invoke(ExternalProductNewImportVo importVo, AnalysisContext context) {
+        try {
+            // 校验必填字段
+            if (ObjectUtil.isEmpty(importVo.getProductNo())) {
+                failureNum++;
+                failureMsg.append("<br/>").append(failureNum).append("、第 ").append(context.readRowHolder().getRowIndex() + 1).append(" 行,产品编号不能为空");
+                return;
+            }
+
+            if (ObjectUtil.isEmpty(importVo.getItemNo())) {
+                failureNum++;
+                failureMsg.append("<br/>").append(failureNum).append("、第 ").append(context.readRowHolder().getRowIndex() + 1).append(" 行,项目编号不能为空");
+                return;
+            }
+
+            // 根据产品编号查询是否已存在
+            List<ExternalProduct> existingList = externalProductService.list(Wrappers.<ExternalProduct>lambdaQuery()
+                .eq(ExternalProduct::getProductNo, importVo.getProductNo()));
+
+            // 获取项目 ID(通过项目编号)
+            Long itemId = null;
+            if (ObjectUtil.isNotEmpty(importVo.getItemNo())) {
+                ExternalItem item = externalItemService.getOne(
+                    Wrappers.<ExternalItem>lambdaQuery()
+                        .eq(ExternalItem::getItemNo, importVo.getItemNo())
+                );
+                if (ObjectUtil.isNotEmpty(item)) {
+                    itemId = item.getId();
+                }
+            }
+
+            //获取产品 ID
+            Long productId = remoteProductService.getProductIdProductNo(importVo.getProductNo());
+
+            if (ObjectUtil.isNotEmpty(existingList)) {
+                // 如果已存在,则更新
+                ExternalProduct existing = existingList.get(0);
+                // 校验是否属于同一个项目
+                if (itemId != null && !itemId.equals(existing.getItemId())) {
+                    failureNum++;
+                    failureMsg.append("<br/>").append(failureNum).append("、第 ").append(context.readRowHolder().getRowIndex() + 1).append(" 行,产品编号已存在于其他项目");
+                    return;
+                }
+
+                ExternalProductBo updateBo = new ExternalProductBo();
+                updateBo.setId(existing.getId());
+                updateBo.setProductId(productId);
+                updateBo.setItemId(itemId != null ? itemId : existing.getItemId());
+                updateBo.setProductNo(importVo.getProductNo());
+                updateBo.setExternalPrice(importVo.getAgreementPrice());
+                updateBo.setMinOrderQuantity(importVo.getMinOrderQuantity());
+                // 设置新增字段
+                ValidatorUtils.validate(updateBo);
+                updateBo.setUpdateBy(LoginHelper.getUserId());
+                externalProductService.updateByBo(updateBo);
+                successNum++;
+                successMsg.append("<br/>").append(successNum).append("、产品编号 ").append(importVo.getProductNo()).append(" 更新成功");
+            } else {
+                // 如果不存在,则新增
+                ExternalProductBo insertBo = new ExternalProductBo();
+                insertBo.setItemId(itemId);
+                insertBo.setProductId(productId);
+                insertBo.setProductNo(importVo.getProductNo());
+                insertBo.setExternalPrice(importVo.getAgreementPrice());
+                insertBo.setMinOrderQuantity(importVo.getMinOrderQuantity());
+                // 设置新增字段
+
+                ValidatorUtils.validate(insertBo);
+                insertBo.setCreateBy(LoginHelper.getUserId());
+                externalProductService.insertByBo(insertBo);
+                successNum++;
+                successMsg.append("<br/>").append(successNum).append("、产品编号 ").append(importVo.getProductNo()).append(" 导入成功");
+            }
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>" + failureNum + "、产品编号 " + importVo.getProductNo() + " 导入失败:";
+            String message = e.getMessage();
+            if (e instanceof ConstraintViolationException cvException) {
+                message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
+            }
+            failureMsg.append(msg).append(message);
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+
+    }
+
+    @Override
+    public ExcelResult<ExternalProductNewImportVo> getExcelResult() {
+        return new ExcelResult<ExternalProductNewImportVo>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<ExternalProductNewImportVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}

+ 12 - 2
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/IExternalProductService.java

@@ -17,7 +17,7 @@ import java.util.List;
  * @author LionLi
  * @date 2026-01-08
  */
-public interface IExternalProductService extends IService<ExternalProduct>{
+public interface IExternalProductService extends IService<ExternalProduct> {
 
     /**
      * 查询对外部推送商品
@@ -94,10 +94,20 @@ public interface IExternalProductService extends IService<ExternalProduct>{
      */
     Boolean shelfReview(ExternalProductBo bo);
 
+    /**
+     * 商品批量上下架
+     */
+    boolean batchShelfReview(List<ExternalProductBo> externalProductBos);
+
+    Boolean batchShelfReviewTest(String[] productNos, Integer status);
     /**
      * 获取所有商品列表
      */
     List<ExternalProductVo> getAllProductList();
 
-    boolean saveExternalBatch(Long itemId,List<ProductVo> boList);
+    boolean saveExternalBatch(Long itemId, List<ProductVo> boList);
+
+
+
+
 }

+ 10 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductCategoryServiceImpl.java

@@ -118,6 +118,16 @@ public class ExternalProductCategoryServiceImpl  extends ServiceImpl<ExternalPro
     public Boolean insertByBo(ExternalProductCategoryBo bo) {
         ExternalProductCategory add = MapstructUtils.convert(bo, ExternalProductCategory.class);
         validEntityBeforeSave(add);
+        if (ObjectUtil.isNotNull(add.getParentId())) {
+            ExternalProductCategory parent = baseMapper.selectById(bo.getParentId());
+            add.setAncestors(parent.getAncestors() + StringUtils.SEPARATOR + parent.getId());
+            add.setClassLevel(add.getAncestors().split(",").length + 1L);
+        } else {
+            add.setParentId(0L);
+            add.setAncestors("0");
+            add.setClassLevel(1L);
+        }
+
         boolean flag = baseMapper.insert(add) > 0;
         if (flag) {
             bo.setId(add.getId());

+ 98 - 24
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/service/impl/ExternalProductServiceImpl.java

@@ -2,10 +2,12 @@ package org.dromara.external.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 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.StreamUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -14,6 +16,8 @@ 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.api.zhongche.domain.bo.GoodsDetailBo;
+import org.dromara.external.api.zhongche.domain.bo.GoodsImportBo;
 import org.dromara.external.domain.ExternalItem;
 import org.dromara.external.domain.ExternalProductCategory;
 import org.dromara.external.handler.ProductPushStrategy;
@@ -170,37 +174,37 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
     public TableDataInfo<ExternalProductVo> getThirdProductPage(ExternalProductBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<ExternalProduct> lambdaQueryWrapper = buildQueryWrapper(bo);
         Page<ExternalProductVo> result = baseMapper.selectVoPage(pageQuery.build(),lambdaQueryWrapper );
-        result.getRecords().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 = result.getRecords().stream()
             .map(ExternalProductVo::getExternalCategoryId)
             .filter(Objects::nonNull)
             .collect(Collectors.toSet());
-        if (!categoryIds.isEmpty()) {
-
+        Map<Long, String> categoryMap = new HashMap<>();
+        if (CollUtil.isNotEmpty(categoryIds)) {
             List<ExternalProductCategory> categoryList =
                 externalProductCategoryService.listByIds(categoryIds);
 
             // 转成 Map <id, name>
-            Map<Long, String> categoryMap = categoryList.stream()
+            categoryMap = categoryList.stream()
                 .collect(Collectors.toMap(
                     ExternalProductCategory::getId,
                     ExternalProductCategory::getCategoryName
                 ));
-
+        }
             // 回填分类名称
-            result.getRecords().forEach(item -> {
-                String categoryName =
-                    categoryMap.get(item.getExternalCategoryId());
-                item.setStandardCatalogName(categoryName);
+        Map<Long, String> finalCategoryMap = categoryMap;
+        result.getRecords().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());
+                item.setTotalInventory(externalProductVo.getTotalInventory());
+                if(ObjectUtil.isNotEmpty(finalCategoryMap)){
+                    String categoryName = finalCategoryMap.get(item.getExternalCategoryId());
+                    item.setStandardCatalogName(categoryName);
+                }
             });
-        }
         return TableDataInfo.build( result);
     }
 
@@ -227,7 +231,6 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
         if (CollUtil.isNotEmpty(invalidIds)) {
             throw new ServiceException("存在未设置第三方价格或品类的商品,请先完善后再推送");
         }
-
         // 2️⃣ 直接拿第一个的 itemId
         Long itemId = externalProducts.get(0).getItemId();
 
@@ -242,8 +245,22 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
         ProductPushStrategy strategy =
             strategyFactory.getStrategy(itemKey);
 
-        // 5️⃣ 执行推送
-        strategy.push(itemId,externalProducts);
+        // 5️⃣ 执行推送 筛选出需要推送的和更新的
+        List<ExternalProduct> externalProducts1 = externalProducts.stream().filter(e -> e.getPushStatus() == 0).toList();
+        //将id转换成,分隔的字符串
+        List<Long> productIds = externalProducts.stream().filter(e -> e.getPushStatus() == 1).map(ExternalProduct::getProductId).toList();
+
+        if (externalProducts1.size() > 0) {
+            strategy.push(itemId,externalProducts1);
+        }
+        if (ObjectUtil.isNotEmpty(productIds)) {
+            //获取需要推送的商品数据
+            List<ProductVo> productDetails = remoteProductService.getProductDetails(productIds);
+//            strategy.updatePrice(productDetails);
+            strategy.updateDetail(itemId,productDetails);
+            strategy.updateProperties(itemId,productDetails);
+            strategy.updateImages(itemId,productDetails);
+        }
         return baseMapper.update(Wrappers.lambdaUpdate(ExternalProduct.class)
             .set(ExternalProduct::getPushStatus, 1)
             .in(ExternalProduct::getId, ids));
@@ -257,12 +274,74 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
      */
     @Override
     public Boolean shelfReview(ExternalProductBo bo) {
+        ExternalProductVo externalProductVo = baseMapper.selectVoById(bo.getId());
+        // 2️⃣ 直接拿第一个的 itemId
+        Long itemId = externalProductVo.getItemId();
+
+        // 3️⃣ 查询项目
+        ExternalItem item = externalItemService.getById(itemId);
+
+        String itemKey = item.getItemKey();
+        // 4️⃣ 获取策略
+        ProductPushStrategy strategy =
+            strategyFactory.getStrategy(itemKey);
+
+        // 5️⃣ 执行上下架
+       strategy.updateStatus(List.of(externalProductVo.getProductNo()), bo.getProductStatus());
        return baseMapper.update(Wrappers.lambdaUpdate(ExternalProduct.class)
             .set(ExternalProduct::getProductStatus, bo.getProductStatus())
             .eq(ExternalProduct::getId, bo.getId())
         )>0;
     }
 
+    /**
+     * 商品批量上下架
+     *
+     * @param externalProductBos
+     */
+    @Override
+    public boolean batchShelfReview(List<ExternalProductBo> externalProductBos) {
+        List<ExternalProductVo> externalProductVos = externalProductBos.stream().map(item -> {
+            ExternalProductVo externalProductVo = baseMapper.selectVoById(item.getId());
+            return externalProductVo;
+        }).toList();
+        // 2️⃣ 直接拿第一个的 itemId
+        Long itemId = externalProductVos.get(0).getItemId();
+
+        // 3️⃣ 查询项目
+        ExternalItem item = externalItemService.getById(itemId);
+        if (item == null) {
+            return false;
+        }
+
+        String itemKey = item.getItemKey();
+        // 4️⃣ 获取策略
+        ProductPushStrategy strategy =
+            strategyFactory.getStrategy(itemKey);
+
+        Integer productStatus = externalProductBos.get(0).getProductStatus();
+        List<String> productNos = externalProductVos.stream().map(ExternalProductVo::getProductNo).toList();
+        // 5️⃣ 执行推送
+        strategy.updateStatus(productNos,productStatus );
+        return baseMapper.update(Wrappers.lambdaUpdate(ExternalProduct.class)
+            .set(ExternalProduct::getProductStatus, productStatus)
+            .in(ExternalProduct::getProductNo, productNos)
+            .eq(ExternalProduct::getItemId, itemId)
+        )>0;
+    }
+
+    /**
+    *测试批量上下架
+    * */
+    @Override
+    public Boolean batchShelfReviewTest(String[] productNos, Integer status) {
+        // 4️⃣ 获取策略
+        ProductPushStrategy strategy =
+            strategyFactory.getStrategy("zhongche");
+        strategy.updateStatus(Arrays.asList(productNos),status);
+        return true;
+    }
+
     @Override
     public List<ExternalProductVo> getAllProductList() {
         List<ExternalProductVo> externalProductVos = baseMapper.selectVoList(new LambdaQueryWrapper<ExternalProduct>().eq(ExternalProduct::getPushStatus, 0));
@@ -313,11 +392,6 @@ public class ExternalProductServiceImpl  extends ServiceImpl<ExternalProductMapp
             }
         }
 
-        //查询所有商品信息
-        List<Long> productIds = externalProductVos.stream()
-            .map(ExternalProductVo::getProductId)
-            .toList();
-
 
 
         return externalProductVos;

+ 44 - 44
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/DataMigration.java

@@ -11,9 +11,9 @@ public class DataMigration {
 
 
     // SQL Server 连接信息
-    private static final String SQL_SERVER_URL = "jdbc:sqlserver://119.97.180.89:1433;databaseName=Yoe365Pro;";
+    private static final String SQL_SERVER_URL = "jdbc:sqlserver://192.168.1.123:1433;databaseName=yoe_db;";
     private static final String SQL_SERVER_USER = "sa";
-    private static final String SQL_SERVER_PASS = "Dhx365!123";
+    private static final String SQL_SERVER_PASS = "Sql123456";
 
     // MySQL 连接信息
     private static final String MYSQL_URL = "jdbc:mysql://127.0.0.1:3306/yoe_product_db?useSSL=false&serverTimezone=UTC";
@@ -32,48 +32,48 @@ public class DataMigration {
     private static final int PAGE_SIZE = 10_000;
 
     public static void main(String[] args) {
-//        try (Connection sqlConn = DriverManager.getConnection(SQL_SERVER_URL, SQL_SERVER_USER, SQL_SERVER_PASS)) {
-//            // 先迁移依赖表(品牌、分类、单位、售后)
-//            try (Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASS)) {
-//                loadMappings(mysqlConn);
-//            }
-//            // 再多线程迁移主表 product_info
-//            migrateData(sqlConn); // 注意:现在只传 sqlConn(但内部线程会新建连接)
-//            System.out.println("✅ 所有数据迁移完成!");
-//
-//        } catch (Exception e) {
-//            e.printStackTrace();
-//        }
-
-        try {
-            // 1. 加载 product_no -> id 映射(从已迁移的 product_base 表)
-            loadProductNoMapping();
-            System.out.println("✅ 已加载 " + productNoToId.size() + " 个 product_no 映射");
-
-            // 2. 获取 ID 范围
-            RangeInfo range = getMssqlIdRange();
-            System.out.println("📊 总记录数: " + range.totalCount + ", ID 范围: [" + range.minId + ", " + range.maxId + "]");
-
-            // 3. 划分任务
-            List<TaskRange> tasks = splitTasks(range.minId, range.maxId, PAGE_SIZE);
-            System.out.println("🧩 共划分 " + tasks.size() + " 个任务");
-
-            // 4. 并行执行
-            ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
-            List<Future<Long>> futures = new ArrayList<>();
-
-            for (TaskRange task : tasks) {
-                futures.add(executor.submit(new PhotoMigrationTask(task)));
+        try (Connection sqlConn = DriverManager.getConnection(SQL_SERVER_URL, SQL_SERVER_USER, SQL_SERVER_PASS)) {
+            // 先迁移依赖表(品牌、分类、单位、售后)
+            try (Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASS)) {
+                loadMappings(mysqlConn);
             }
+            // 再多线程迁移主表 product_info
+            migrateData(sqlConn); // 注意:现在只传 sqlConn(但内部线程会新建连接)
+            System.out.println("✅ 所有数据迁移完成!");
 
-            long total = 0;
-            for (Future<Long> f : futures) total += f.get();
-            executor.shutdown();
-
-            System.out.println("🎉 图片表迁移完成!共 " + total + " 条记录。");
         } catch (Exception e) {
             e.printStackTrace();
         }
+
+//        try {
+//            // 1. 加载 product_no -> id 映射(从已迁移的 product_base 表)
+//            loadProductNoMapping();
+//            System.out.println("✅ 已加载 " + productNoToId.size() + " 个 product_no 映射");
+//
+//            // 2. 获取 ID 范围
+//            RangeInfo range = getMssqlIdRange();
+//            System.out.println("📊 总记录数: " + range.totalCount + ", ID 范围: [" + range.minId + ", " + range.maxId + "]");
+//
+//            // 3. 划分任务
+//            List<TaskRange> tasks = splitTasks(range.minId, range.maxId, PAGE_SIZE);
+//            System.out.println("🧩 共划分 " + tasks.size() + " 个任务");
+//
+//            // 4. 并行执行
+//            ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
+//            List<Future<Long>> futures = new ArrayList<>();
+//
+//            for (TaskRange task : tasks) {
+//                futures.add(executor.submit(new PhotoMigrationTask(task)));
+//            }
+//
+//            long total = 0;
+//            for (Future<Long> f : futures) total += f.get();
+//            executor.shutdown();
+//
+//            System.out.println("🎉 图片表迁移完成!共 " + total + " 条记录。");
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
     }
 
     /**
@@ -437,7 +437,7 @@ public class DataMigration {
             mysqlConn.setAutoCommit(false);
 
             // 准备语句
-            PreparedStatement baseStmt = prepareBaseInsert(mysqlConn);
+//            PreparedStatement baseStmt = prepareBaseInsert(mysqlConn);
             PreparedStatement priceStmt = preparePriceInsert(mysqlConn);
             PreparedStatement extendStmt = prepareExtendInsert(mysqlConn);
 
@@ -453,8 +453,8 @@ public class DataMigration {
                         boolean hasData = false;
                         while (rs.next()) {
                             hasData = true;
-                            setBaseValues(baseStmt, rs);
-                            baseStmt.addBatch();
+//                            setBaseValues(baseStmt, rs);
+//                            baseStmt.addBatch();
 
                             setPriceValues(priceStmt, rs);
                             priceStmt.addBatch();
@@ -464,7 +464,7 @@ public class DataMigration {
                         }
 
                         if (hasData) {
-                            baseStmt.executeBatch();
+//                            baseStmt.executeBatch();
                             priceStmt.executeBatch();
                             extendStmt.executeBatch();
                             mysqlConn.commit();
@@ -475,7 +475,7 @@ public class DataMigration {
                 }
             } finally {
                 // 关闭所有 PreparedStatement
-                try { baseStmt.close(); } catch (Exception ignored) {}
+//                try { baseStmt.close(); } catch (Exception ignored) {}
                 try { priceStmt.close(); } catch (Exception ignored) {}
                 try { extendStmt.close(); } catch (Exception ignored) {}
             }

+ 104 - 0
ruoyi-modules/ruoyi-external/src/main/java/org/dromara/external/util/ProductPhotoImporter.java

@@ -0,0 +1,104 @@
+package org.dromara.external.util;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ProductPhotoImporter {
+
+    private static final String MYSQL_URL = "jdbc:mysql://127.0.0.1:3306/yoe_product_db?useSSL=false&serverTimezone=UTC";
+    private static final String MYSQL_USER = "root";
+    private static final String MYSQL_PASS = "root";
+
+    public static void main(String[] args) throws IOException {
+        // 模拟读取你的 INSERT 语句文本
+        // 实际使用中,你可以从文件读取:String sqlContent = new String(Files.readAllBytes(Paths.get("inserts.sql")));
+        String sqlContent = loadYourInsertStatements();
+
+        // 1. 解析 SQL 文本
+        // 匹配 INSERT INTO ... VALUES ( ... 'product_no', 'image_url', 'pc_html', 'app_html' ... )
+        // 这个正则比较复杂,因为我们只需要 product_no 和后面紧跟着的几个大字段
+// 强大的正则,能处理 N'...'、换行符和转义引号
+        Pattern insertPattern = Pattern.compile(
+            "INSERT INTO \\[\\] .*? VALUES \\([^,]+?,[^,]+?,\\s*N?'(.*?)',\\s*N?'(.*?)',\\s*N?'(.*?)',\\s*N?'(.*?)',\\s*N?'(.*?)'",
+            Pattern.CASE_INSENSITIVE | Pattern.DOTALL // 必须加上 DOTALL 标志
+        );
+
+        Matcher matcher = insertPattern.matcher(sqlContent);
+
+        try (Connection conn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASS)) {
+            // 关闭自动提交,提高批量插入性能
+            conn.setAutoCommit(false);
+
+            // 2. 预编译查询语句 (检查 product_base)
+            String checkSql = "SELECT 1 FROM product_base WHERE product_no = ? AND del_flag = '0'";
+            PreparedStatement checkStmt = conn.prepareStatement(checkSql);
+
+            // 3. 预编译插入语句 (插入 product_photos)
+            // 注意:这里假设插入时使用数据库自增 ID (product_id),所以 SQL 中不包含第一个字段
+            String insertSql = "INSERT INTO product_photos " +
+                "(image_no, product_no, image_url, product_details_pc, product_details_app, create_time, update_time) " +
+                "VALUES (?, ?, ?, ?, ?, NOW(), NOW())";
+            PreparedStatement insertStmt = conn.prepareStatement(insertSql);
+
+            int count = 0;
+            while (matcher.find()) {
+                String productNo = matcher.group(1);
+                String imageUrl = matcher.group(2);
+                String pcHtml = matcher.group(3);
+                String appHtml = matcher.group(4);
+
+                // 4. 检查主表是否存在
+                checkStmt.setString(1, productNo);
+                ResultSet rs = checkStmt.executeQuery();
+
+                if (rs.next()) {
+                    // 5. 如果存在,插入图片表
+                    // image_no 为空,设为 null
+                    insertStmt.setNull(1, Types.VARCHAR);
+                    insertStmt.setString(2, productNo);
+                    insertStmt.setString(3, imageUrl);
+                    insertStmt.setString(4, pcHtml);
+                    insertStmt.setString(5, appHtml);
+
+                    insertStmt.addBatch();
+                    count++;
+
+                    // 每 1000 条提交一次
+                    if (count % 1000 == 0) {
+                        insertStmt.executeBatch();
+                        conn.commit();
+                        System.out.println("已提交 " + count + " 条记录");
+                    }
+                } else {
+                    System.out.println("跳过 product_no: " + productNo + " (主表中不存在或已删除)");
+                }
+                rs.close();
+            }
+
+            // 提交剩余的数据
+            insertStmt.executeBatch();
+            conn.commit();
+            System.out.println("导入完成,共处理 " + count + " 条有效数据");
+
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+    }
+
+    // 模拟读取你上传的文件内容
+    // 请将此处的字符串替换为实际读取文件的逻辑
+    private static String loadYourInsertStatements() throws IOException {
+        // 这里直接返回你提供的部分字符串作为演示
+        // 实际运行时,请读取你的 INSERT INT.txt 文件内容
+        // 一次性读取整个文件内容
+        Path path = Paths.get("E://sql.txt");
+        String sqlContent = Files.readString(path, StandardCharsets.UTF_8);
+        return sqlContent; // 你的长文本
+    }
+}

+ 1 - 2
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/pc/PcOrderController.java

@@ -376,8 +376,7 @@ public class PcOrderController extends BaseController {
 
 
             // 如果远程服务只接受字符串
-            String productIdStr = productIds.stream().map(String::valueOf).collect(Collectors.joining(","));
-            List<ProductVo> productDetails = remoteProductService.getProductDetails(productIdStr);
+            List<ProductVo> productDetails = remoteProductService.getProductDetails(productIds);
 
             // 4. 构建订单商品列表
             List<OrderProductBo> orderProductBos = productDetails.stream()

+ 126 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductBaseAuditController.java

@@ -0,0 +1,126 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.product.domain.ProductBaseAudit;
+import org.dromara.product.domain.bo.ProductAuditBo;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProductBaseAuditVo;
+import org.dromara.product.domain.bo.ProductBaseAuditBo;
+import org.dromara.product.service.IProductBaseAuditService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 商品审核
+ * 前端访问路由地址为:/product/baseAudit
+ *
+ * @author LionLi
+ * @date 2026-04-06
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/baseAudit")
+public class ProductBaseAuditController extends BaseController {
+
+    private final IProductBaseAuditService productBaseAuditService;
+
+    /**
+     * 查询商品审核列表
+     */
+    //@SaCheckPermission("product:baseAudit:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProductBaseAuditVo> list(ProductBaseAuditBo bo, PageQuery pageQuery) {
+        return productBaseAuditService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出商品审核列表
+     */
+    //@SaCheckPermission("product:baseAudit:export")
+    @Log(title = "商品审核", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProductBaseAuditBo bo, HttpServletResponse response) {
+        List<ProductBaseAuditVo> list = productBaseAuditService.queryList(bo);
+        ExcelUtil.exportExcel(list, "商品审核", ProductBaseAuditVo.class, response);
+    }
+
+    /**
+     * 获取商品审核详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:baseAudit:query")
+    @GetMapping("/{id}")
+    public R<ProductBaseAuditVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(productBaseAuditService.queryById(id));
+    }
+
+    /**
+     * 新增商品审核
+     */
+    //@SaCheckPermission("product:baseAudit:add")
+    @Log(title = "商品审核", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProductBaseAuditBo bo) {
+        return toAjax(productBaseAuditService.insertByBo(bo));
+    }
+
+    /**
+     * 修改商品审核
+     */
+    //@SaCheckPermission("product:baseAudit:edit")
+    @Log(title = "商品审核", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProductBaseAuditBo bo) {
+        return toAjax(productBaseAuditService.updateByBo(bo));
+    }
+
+    /**
+     * 删除商品审核
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:baseAudit:remove")
+    @Log(title = "商品审核", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(productBaseAuditService.deleteWithValidByIds(List.of(ids), true));
+    }
+
+    /**
+    * 审核商品
+    * */
+    @PostMapping("/audit")
+    public R<Void> audit(@RequestBody ProductAuditBo bo) {
+        productBaseAuditService.audit(bo);
+        return R.ok();
+    }
+
+    /**
+    * 提交审核
+    * */
+    @PostMapping("/commit")
+    public R<Void> commit(@RequestBody ProductBaseAuditBo bo) {
+        productBaseAuditService.commit(bo);
+        return R.ok();
+    }
+}

+ 20 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductBaseController.java

@@ -3,10 +3,13 @@ package org.dromara.product.controller;
 import java.util.List;
 
 import cn.hutool.core.lang.tree.Tree;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.product.domain.ProductBaseAudit;
 import org.dromara.product.domain.bo.*;
 import org.dromara.product.domain.vo.*;
 import org.dromara.product.service.*;
@@ -50,6 +53,8 @@ public class ProductBaseController extends BaseController {
 
     private final IProductUnitService productUnitService;
 
+    private final IProductBaseAuditService productBaseAuditService;
+
     /**
      * 查询产品基础信息列表
      */
@@ -219,7 +224,21 @@ public class ProductBaseController extends BaseController {
      */
     @PostMapping("/shelfReview")
     public R<Void> shelfReview(@Validated @RequestBody ProductBaseBo bo) {
-        productBaseService.shelfReview(bo);
+        //如果提交了审核不能再次提交
+        boolean exists = productBaseAuditService.exists(Wrappers.lambdaQuery(ProductBaseAudit.class)
+            .eq(ProductBaseAudit::getProductId, bo.getId())
+            .eq(ProductBaseAudit::getType, 1L)
+        );
+        if (exists) {
+            return R.fail("商品已提交上架审核,请勿重复提交");
+        }
+        ProductBaseVo productBaseVo = productBaseService.queryById(bo.getId());
+        ProductBaseAuditBo productBaseAuditBo = new ProductBaseAuditBo();
+        productBaseAuditBo.setProductId(bo.getId());
+        productBaseAuditBo.setAuditStatus(1L);
+        productBaseAuditBo.setType(1L);
+        productBaseAuditBo.setProductData(JSONUtil.toJsonStr(productBaseVo));
+        productBaseAuditService.insertByBo(productBaseAuditBo);
         return R.ok();
     }
 

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductCategoryA10Controller.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProductCategoryA10Vo;
+import org.dromara.product.domain.bo.ProductCategoryA10Bo;
+import org.dromara.product.service.IProductCategoryA10Service;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 产品分类A10
+ * 前端访问路由地址为:/product/categoryA10
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/categoryA10")
+public class ProductCategoryA10Controller extends BaseController {
+
+    private final IProductCategoryA10Service productCategoryA10Service;
+
+    /**
+     * 查询产品分类A10列表
+     */
+    //@SaCheckPermission("product:categoryA10:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProductCategoryA10Vo> list(ProductCategoryA10Bo bo, PageQuery pageQuery) {
+        return productCategoryA10Service.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出产品分类A10列表
+     */
+    //@SaCheckPermission("product:categoryA10:export")
+    @Log(title = "产品分类A10", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProductCategoryA10Bo bo, HttpServletResponse response) {
+        List<ProductCategoryA10Vo> list = productCategoryA10Service.queryList(bo);
+        ExcelUtil.exportExcel(list, "产品分类A10", ProductCategoryA10Vo.class, response);
+    }
+
+    /**
+     * 获取产品分类A10详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:categoryA10:query")
+    @GetMapping("/{id}")
+    public R<ProductCategoryA10Vo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(productCategoryA10Service.queryById(id));
+    }
+
+    /**
+     * 新增产品分类A10
+     */
+    //@SaCheckPermission("product:categoryA10:add")
+    @Log(title = "产品分类A10", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProductCategoryA10Bo bo) {
+        return toAjax(productCategoryA10Service.insertByBo(bo));
+    }
+
+    /**
+     * 修改产品分类A10
+     */
+    //@SaCheckPermission("product:categoryA10:edit")
+    @Log(title = "产品分类A10", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProductCategoryA10Bo bo) {
+        return toAjax(productCategoryA10Service.updateByBo(bo));
+    }
+
+    /**
+     * 删除产品分类A10
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:categoryA10:remove")
+    @Log(title = "产品分类A10", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(productCategoryA10Service.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductCategoryCustomerController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProductCategoryCustomerVo;
+import org.dromara.product.domain.bo.ProductCategoryCustomerBo;
+import org.dromara.product.service.IProductCategoryCustomerService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 产品分类客户
+ * 前端访问路由地址为:/product/categoryCustomer
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/categoryCustomer")
+public class ProductCategoryCustomerController extends BaseController {
+
+    private final IProductCategoryCustomerService productCategoryCustomerService;
+
+    /**
+     * 查询产品分类客户列表
+     */
+    //@SaCheckPermission("product:categoryCustomer:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProductCategoryCustomerVo> list(ProductCategoryCustomerBo bo, PageQuery pageQuery) {
+        return productCategoryCustomerService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出产品分类客户列表
+     */
+    //@SaCheckPermission("product:categoryCustomer:export")
+    @Log(title = "产品分类客户", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProductCategoryCustomerBo bo, HttpServletResponse response) {
+        List<ProductCategoryCustomerVo> list = productCategoryCustomerService.queryList(bo);
+        ExcelUtil.exportExcel(list, "产品分类客户", ProductCategoryCustomerVo.class, response);
+    }
+
+    /**
+     * 获取产品分类客户详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:categoryCustomer:query")
+    @GetMapping("/{id}")
+    public R<ProductCategoryCustomerVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(productCategoryCustomerService.queryById(id));
+    }
+
+    /**
+     * 新增产品分类客户
+     */
+    //@SaCheckPermission("product:categoryCustomer:add")
+    @Log(title = "产品分类客户", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProductCategoryCustomerBo bo) {
+        return toAjax(productCategoryCustomerService.insertByBo(bo));
+    }
+
+    /**
+     * 修改产品分类客户
+     */
+    //@SaCheckPermission("product:categoryCustomer:edit")
+    @Log(title = "产品分类客户", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProductCategoryCustomerBo bo) {
+        return toAjax(productCategoryCustomerService.updateByBo(bo));
+    }
+
+    /**
+     * 删除产品分类客户
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:categoryCustomer:remove")
+    @Log(title = "产品分类客户", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(productCategoryCustomerService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductClassificationDiyController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ProductClassificationDiyVo;
+import org.dromara.product.domain.bo.ProductClassificationDiyBo;
+import org.dromara.product.service.IProductClassificationDiyService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 商品自定义属性
+ * 前端访问路由地址为:/product/classificationDiy
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/classificationDiy")
+public class ProductClassificationDiyController extends BaseController {
+
+    private final IProductClassificationDiyService productClassificationDiyService;
+
+    /**
+     * 查询商品自定义属性列表
+     */
+    //@SaCheckPermission("product:classificationDiy:list")
+    @GetMapping("/list")
+    public TableDataInfo<ProductClassificationDiyVo> list(ProductClassificationDiyBo bo, PageQuery pageQuery) {
+        return productClassificationDiyService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出商品自定义属性列表
+     */
+    //@SaCheckPermission("product:classificationDiy:export")
+    @Log(title = "商品自定义属性", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ProductClassificationDiyBo bo, HttpServletResponse response) {
+        List<ProductClassificationDiyVo> list = productClassificationDiyService.queryList(bo);
+        ExcelUtil.exportExcel(list, "商品自定义属性", ProductClassificationDiyVo.class, response);
+    }
+
+    /**
+     * 获取商品自定义属性详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("product:classificationDiy:query")
+    @GetMapping("/{id}")
+    public R<ProductClassificationDiyVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(productClassificationDiyService.queryById(id));
+    }
+
+    /**
+     * 新增商品自定义属性
+     */
+    //@SaCheckPermission("product:classificationDiy:add")
+    @Log(title = "商品自定义属性", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ProductClassificationDiyBo bo) {
+        return toAjax(productClassificationDiyService.insertByBo(bo));
+    }
+
+    /**
+     * 修改商品自定义属性
+     */
+    //@SaCheckPermission("product:classificationDiy:edit")
+    @Log(title = "商品自定义属性", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ProductClassificationDiyBo bo) {
+        return toAjax(productClassificationDiyService.updateByBo(bo));
+    }
+
+    /**
+     * 删除商品自定义属性
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("product:classificationDiy:remove")
+    @Log(title = "商品自定义属性", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(productClassificationDiyService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 36 - 8
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ProductPoolAuditController.java

@@ -7,9 +7,12 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import org.dromara.product.domain.ProductPoolAudit;
+import org.dromara.product.domain.ProductPoolLinkAudit;
 import org.dromara.product.domain.bo.ProductBaseBo;
 import org.dromara.product.domain.bo.ProductPoolAuditBatchBo;
 import org.dromara.product.domain.vo.ProductBaseVo;
+import org.dromara.product.domain.vo.ProductListVo;
+import org.dromara.product.service.IProductPoolLinkAuditService;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -41,6 +44,8 @@ public class ProductPoolAuditController extends BaseController {
 
     private final IProductPoolAuditService productPoolAuditService;
 
+    private final IProductPoolLinkAuditService productPoolLinkAuditService;
+
     /**
      * 查询产品池审核列表
      */
@@ -69,7 +74,7 @@ public class ProductPoolAuditController extends BaseController {
     //@SaCheckPermission("product:poolAudit:query")
     @GetMapping("/{id}")
     public R<ProductPoolAuditVo> getInfo(@NotNull(message = "主键不能为空")
-                                     @PathVariable("id") Long id) {
+                                         @PathVariable("id") Long id) {
         return R.ok(productPoolAuditService.queryById(id));
     }
 
@@ -109,8 +114,16 @@ public class ProductPoolAuditController extends BaseController {
     }
 
     /**
-    * 获取审核池里的商品
-    * */
+     * 查询审核池商品列表
+     */
+    @GetMapping("/selectPoolAuditProductPage")
+    public TableDataInfo<ProductListVo> selectPoolAuditProductPage(ProductBaseBo bo, PageQuery pageQuery) {
+        return productPoolAuditService.selectPoolAuditProductPage(bo, pageQuery);
+    }
+
+    /**
+     * 获取审核池里的商品
+     */
     @GetMapping("/getPoolAuditProductPage")
     public TableDataInfo<ProductBaseVo> getPoolAuditProductPage(ProductBaseBo bo, PageQuery pageQuery) {
         return productPoolAuditService.getPoolAuditProductPage(bo, pageQuery);
@@ -131,10 +144,9 @@ public class ProductPoolAuditController extends BaseController {
     }
 
 
-
     /**
-    * 清空审核池
-    * */
+     * 清空审核池
+     */
     @Log(title = "清空审核池", businessType = BusinessType.DELETE)
     @DeleteMapping("/clearPool")
     public R<Void> clearPool(@NotNull(message = "主键不能为空") @PathVariable("id") Long id) {
@@ -142,8 +154,8 @@ public class ProductPoolAuditController extends BaseController {
     }
 
     /**
-    * 提交审核
-    * */
+     * 提交审核
+     */
     @Log(title = "产品池审核", businessType = BusinessType.UPDATE)
     @PutMapping("/apply/{id}")
     public R<Void> apply(@NotNull(message = "主键不能为空") @PathVariable("id") Long id) {
@@ -151,6 +163,22 @@ public class ProductPoolAuditController extends BaseController {
             .set(ProductPoolAudit::getProductReviewStatus, "1")
             .eq(ProductPoolAudit::getId, id)
         );
+        productPoolLinkAuditService.update(Wrappers.lambdaUpdate(ProductPoolLinkAudit.class)
+            .eq(ProductPoolLinkAudit::getPoolAuditId, id)
+            .set(ProductPoolLinkAudit::getProductReviewStatus, "1")
+        );
+        return R.ok();
+    }
+
+    /**
+    * 单条记录审核
+    * */
+    @Log(title = "产品池审核", businessType = BusinessType.UPDATE)
+    @PostMapping("/audit")
+    public R<Void> audit(@RequestBody ProductPoolAuditBatchBo bo) {
+        productPoolAuditService.auditProduct(bo);
         return R.ok();
     }
+
+
 }

+ 73 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductBaseAudit.java

@@ -0,0 +1,73 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 商品审核对象 product_base_audit
+ *
+ * @author LionLi
+ * @date 2026-04-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("product_base_audit")
+public class ProductBaseAudit extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回,4=营销审核,5运营审核
+     */
+    private Long auditStatus;
+
+    /**
+     * 审核原因
+     */
+    private String auditReason;
+
+    /**
+     * 审核人
+     */
+    private Long auditUserId;
+
+    /**
+     * 审核时间
+     */
+    private Date auditTime;
+
+    /**
+     * 商品审核数据
+     */
+    private String productData;
+
+    /**
+     * 类型 0=提交审核,1上下架审核
+     */
+    private Long type;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 157 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductCategoryA10.java

@@ -0,0 +1,157 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 产品分类A10对象 product_category_a10
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("product_category_a10")
+public class ProductCategoryA10 extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 分类编号
+     */
+    private String categoryNo;
+
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+
+    /**
+     * 祖籍列表
+     */
+    private String ancestors;
+
+    /**
+     * 分类层级(1=一级,2=二级, 3三级)
+     */
+    private Long classLevel;
+
+    /**
+     * 是否显示(1=显示,0=隐藏)
+     */
+    private Long isShow;
+
+    /**
+     * 是否在GPS中显示
+     */
+    private Long isShowGps;
+
+    /**
+     * 折扣率(可能为JSON或文本)
+     */
+    private Long discountRate;
+
+    /**
+     * 拼音码(用于快速检索)
+     */
+    private String pyCode;
+
+    /**
+     * 分类描述
+     */
+    private String classDescription;
+
+    /**
+     * 数据来源
+     */
+    private String dataSource;
+
+    /**
+     * 自定义标签1
+     */
+    private String oneLable1;
+
+    /**
+     * 自定义标签2
+     */
+    private String oneLable2;
+
+    /**
+     * 自定义链接1
+     */
+    private String oneLink1;
+
+    /**
+     * 自定义链接2
+     */
+    private String oneLink2;
+
+    /**
+     * 排序值,默认为0
+     */
+    private Long sort;
+
+    /**
+     * 审核人员id
+     */
+    private Long reviewerId;
+
+    /**
+     * 颜色(如CSS颜色值)
+     */
+    private String color;
+
+    /**
+     * 采购编号
+     */
+    private String purchaseNo;
+
+    /**
+     * 采购名称
+     */
+    private String purchaseName;
+
+    /**
+     * 采购负责人编号
+     */
+    private String purchaseManagerNo;
+
+    /**
+     * 采购负责人姓名
+     */
+    private String purchaseManagerName;
+
+    /**
+     * 所属平台(0=Web, 1=小程序)
+     */
+    private Long platform;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 162 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductCategoryCustomer.java

@@ -0,0 +1,162 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 产品分类客户对象 product_category_customer
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("product_category_customer")
+public class ProductCategoryCustomer extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 分类编号
+     */
+    private String categoryNo;
+
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+
+    /**
+     * 祖籍列表
+     */
+    private String ancestors;
+
+    /**
+     * 分类层级(1=一级,2=二级, 3三级)
+     */
+    private Long classLevel;
+
+    /**
+     * 是否显示(1=显示,0=隐藏)
+     */
+    private Long isShow;
+
+    /**
+     * 是否在GPS中显示
+     */
+    private Long isShowGps;
+
+    /**
+     * 折扣率(可能为JSON或文本)
+     */
+    private Long discountRate;
+
+    /**
+     * 拼音码(用于快速检索)
+     */
+    private String pyCode;
+
+    /**
+     * 分类描述
+     */
+    private String classDescription;
+
+    /**
+     * 数据来源
+     */
+    private String dataSource;
+
+    /**
+     * 自定义标签1
+     */
+    private String oneLable1;
+
+    /**
+     * 自定义标签2
+     */
+    private String oneLable2;
+
+    /**
+     * 自定义链接1
+     */
+    private String oneLink1;
+
+    /**
+     * 自定义链接2
+     */
+    private String oneLink2;
+
+    /**
+     * 排序值,默认为0
+     */
+    private Long sort;
+
+    /**
+     * 审核人员id
+     */
+    private Long reviewerId;
+
+    /**
+     * 客户id
+     */
+    private Long customerId;
+
+    /**
+     * 颜色(如CSS颜色值)
+     */
+    private String color;
+
+    /**
+     * 采购编号
+     */
+    private String purchaseNo;
+
+    /**
+     * 采购名称
+     */
+    private String purchaseName;
+
+    /**
+     * 采购负责人编号
+     */
+    private String purchaseManagerNo;
+
+    /**
+     * 采购负责人姓名
+     */
+    private String purchaseManagerName;
+
+    /**
+     * 所属平台(0=Web, 1=小程序)
+     */
+    private Long platform;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 51 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductClassificationDiy.java

@@ -0,0 +1,51 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 商品自定义属性对象 product_classification_diy
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("product_classification_diy")
+public class ProductClassificationDiy extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 属性key
+     */
+    private String attributeKey;
+
+    /**
+     * 属性value
+     */
+    private String attributeValue;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductPoolAudit.java

@@ -82,5 +82,10 @@ public class ProductPoolAudit extends TenantEntity {
      * */
     private String attachment;
 
+    /**
+     * 申请类型 0更新,1移出
+     * */
+    private Integer applyType;
+
 
 }

+ 16 - 6
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProductPoolLinkAudit.java

@@ -32,12 +32,8 @@ public class ProductPoolLinkAudit extends TenantEntity {
      * 所属池 ID
      */
     private Long poolId;
-    
-    /**
-     * 项目 id
-     */
-    private Long itemId;
-    
+
+
     /**
      * 审核池 id
      */
@@ -83,5 +79,19 @@ public class ProductPoolLinkAudit extends TenantEntity {
      */
     private String remark;
 
+    /**
+    * 申请类型 0更新,1移出
+    * */
+    private Integer type;
+
+    /**
+     * 计价规则(0 一品一价,1 按类目折扣率报价)
+     * */
+    private String pricingRule;
+    /**
+     * 起订量
+     * */
+    private Long minOrderQuantity;
+
 
 }

+ 24 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductAuditBo.java

@@ -0,0 +1,24 @@
+package org.dromara.product.domain.bo;
+
+import lombok.Data;
+
+/**
+ * 商品审核
+ * @author
+ * @date 2026/4/7 上午12:40
+ */
+@Data
+public class ProductAuditBo {
+    /**
+     * ID 列表
+     */
+    private java.util.List<Long> Ids;
+    /**
+     * 审核状态 2=通过,3=驳回
+     */
+    private String auditStatus;
+    /**
+     * 驳回原因
+     */
+    private String auditReason;
+}

+ 79 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseAuditBo.java

@@ -0,0 +1,79 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProductBaseAudit;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 商品审核业务对象 product_base_audit
+ *
+ * @author LionLi
+ * @date 2026-04-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProductBaseAudit.class, reverseConvertGenerate = false)
+public class ProductBaseAuditBo extends BaseEntity {
+
+    /**
+     *
+     */
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    //@NotNull(message = "商品id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回,4=营销审核,5运营审核
+     */
+    //@NotNull(message = "审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回,4=营销审核,5运营审核不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long auditStatus;
+
+    /**
+     * 审核原因
+     */
+    //@NotBlank(message = "审核原因不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String auditReason;
+
+    /**
+     * 审核人
+     */
+    //@NotNull(message = "审核人不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long auditUserId;
+
+    /**
+     * 审核时间
+     */
+    //@NotNull(message = "审核时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Date auditTime;
+
+    /**
+     * 商品审核数据
+     */
+    //@NotBlank(message = "商品审核数据不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String productData;
+
+    /**
+     * 类型 0=提交审核,1上下架审核
+     */
+    //@NotNull(message = "类型 0=提交审核,1上下架审核不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long type;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 33 - 17
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseBo.java

@@ -11,8 +11,10 @@ import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 import org.dromara.common.translation.annotation.Translation;
 import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.product.domain.ProductClassificationDiy;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * 产品基础信息业务对象 product_base
@@ -176,12 +178,12 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 规格型号
      */
-    private String specification;
+    private String specificationsCode;
 
     /**
      * UPC(S)条码
      */
-    private String upcBarcode;
+    private String barCoding;
 
     /**
      * 发票名称
@@ -196,7 +198,7 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 发票规格
      */
-    private String invoiceSpec;
+    private String invoiceSpecs;
 
     /**
      * 包装规格
@@ -221,7 +223,7 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 商品重量
      */
-    private String weight;
+    private String productWeight;
 
     /**
      * 重量单位
@@ -231,7 +233,7 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 商品体积
      */
-    private String volume;
+    private String productVolume;
 
     /**
      * 体积单位
@@ -266,22 +268,22 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 市场价
      */
-    private java.math.BigDecimal midRangePrice;
+    private java.math.BigDecimal marketPrice;
 
     /**
      * 会员价
      */
-    private java.math.BigDecimal standardPrice;
+    private java.math.BigDecimal memberPrice;
 
     /**
      * 最低售价
      */
-    private java.math.BigDecimal certificatePrice;
+    private java.math.BigDecimal minSellingPrice;
 
     /**
      * 采购价
      */
-    private java.math.BigDecimal purchasePrice;
+    private java.math.BigDecimal purchasingPrice;
 
     /**
      * 暂估采购价
@@ -326,6 +328,11 @@ public class ProductBaseBo extends BaseEntity {
      */
     private String attributesList;
 
+    /**
+     * diy商品属性
+     */
+    private List<ProductClassificationDiy> diyAttributesList;
+
     /**
      * 税率
      */
@@ -344,7 +351,7 @@ public class ProductBaseBo extends BaseEntity {
     /**
      * 是否可定制
      */
-    private Boolean customizable;
+    private String isCustomize;
 
     /**
      * 定制说明
@@ -370,6 +377,11 @@ public class ProductBaseBo extends BaseEntity {
      */
     private String imageUrl;
 
+    /**
+     * 供应商id
+     * */
+    private String supplierNo;
+
     /**
      * 站点id
      */
@@ -391,25 +403,29 @@ public class ProductBaseBo extends BaseEntity {
     private Integer auditStatus;
 
     /**
-    * 对接状态 0未对接,1已对接
+     * 对接状态 0未对接,1已对接
      */
     private Integer connectStatus;
     /**
-    * 推送状态 0未推送,1已推送, 2推送失败
-    * */
+     * 推送状态 0未推送,1已推送, 2推送失败
+     */
     private Integer pushStatus;
 
     /**
      * 税收编码id
-     *
-     * */
+     */
     private Long taxationId;
 
     /**
-    * 产品池审核id
-    * */
+     * 产品池审核id
+     */
     private Long poolAuditId;
 
+    /**
+    * 池类型
+    * */
+    private String poolType;
+
 
 
 }

+ 171 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductCategoryA10Bo.java

@@ -0,0 +1,171 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProductCategoryA10;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 产品分类A10业务对象 product_category_a10
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProductCategoryA10.class, reverseConvertGenerate = false)
+public class ProductCategoryA10Bo extends BaseEntity {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 分类编号
+     */
+    //@NotBlank(message = "分类编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String categoryNo;
+
+    /**
+     * 分类名称
+     */
+    //@NotBlank(message = "分类名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String categoryName;
+
+    /**
+     * 父级分类ID
+     */
+    //@NotNull(message = "父级分类ID不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long parentId;
+
+    /**
+     * 祖籍列表
+     */
+    //@NotBlank(message = "祖籍列表不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String ancestors;
+
+    /**
+     * 分类层级(1=一级,2=二级, 3三级)
+     */
+    private Long classLevel;
+
+    /**
+     * 是否显示(1=显示,0=隐藏)
+     */
+    //@NotNull(message = "是否显示(1=显示,0=隐藏)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long isShow;
+
+    /**
+     * 是否在GPS中显示
+     */
+    private Long isShowGps;
+
+    /**
+     * 折扣率(可能为JSON或文本)
+     */
+    //@NotNull(message = "折扣率(可能为JSON或文本)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long discountRate;
+
+    /**
+     * 拼音码(用于快速检索)
+     */
+    //@NotBlank(message = "拼音码(用于快速检索)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String pyCode;
+
+    /**
+     * 分类描述
+     */
+    //@NotBlank(message = "分类描述不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String classDescription;
+
+    /**
+     * 数据来源
+     */
+    //@NotBlank(message = "数据来源不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String dataSource;
+
+    /**
+     * 自定义标签1
+     */
+    //@NotBlank(message = "自定义标签1不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLable1;
+
+    /**
+     * 自定义标签2
+     */
+    //@NotBlank(message = "自定义标签2不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLable2;
+
+    /**
+     * 自定义链接1
+     */
+    //@NotBlank(message = "自定义链接1不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLink1;
+
+    /**
+     * 自定义链接2
+     */
+    //@NotBlank(message = "自定义链接2不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLink2;
+
+    /**
+     * 排序值,默认为0
+     */
+    //@NotNull(message = "排序值,默认为0不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long sort;
+
+    /**
+     * 审核人员id
+     */
+    //@NotNull(message = "审核人员id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long reviewerId;
+
+    /**
+     * 颜色(如CSS颜色值)
+     */
+    //@NotBlank(message = "颜色(如CSS颜色值)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String color;
+
+    /**
+     * 采购编号
+     */
+    //@NotBlank(message = "采购编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseNo;
+
+    /**
+     * 采购名称
+     */
+    //@NotBlank(message = "采购名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseName;
+
+    /**
+     * 采购负责人编号
+     */
+    //@NotBlank(message = "采购负责人编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseManagerNo;
+
+    /**
+     * 采购负责人姓名
+     */
+    //@NotBlank(message = "采购负责人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseManagerName;
+
+    /**
+     * 所属平台(0=Web, 1=小程序)
+     */
+    //@NotNull(message = "所属平台(0=Web, 1=小程序)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long platform;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 177 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductCategoryCustomerBo.java

@@ -0,0 +1,177 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProductCategoryCustomer;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 产品分类客户业务对象 product_category_customer
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProductCategoryCustomer.class, reverseConvertGenerate = false)
+public class ProductCategoryCustomerBo extends BaseEntity {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 分类编号
+     */
+    //@NotBlank(message = "分类编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String categoryNo;
+
+    /**
+     * 分类名称
+     */
+    //@NotBlank(message = "分类名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String categoryName;
+
+    /**
+     * 父级分类ID
+     */
+    //@NotNull(message = "父级分类ID不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long parentId;
+
+    /**
+     * 祖籍列表
+     */
+    //@NotBlank(message = "祖籍列表不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String ancestors;
+
+    /**
+     * 分类层级(1=一级,2=二级, 3三级)
+     */
+    private Long classLevel;
+
+    /**
+     * 是否显示(1=显示,0=隐藏)
+     */
+    //@NotNull(message = "是否显示(1=显示,0=隐藏)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long isShow;
+
+    /**
+     * 是否在GPS中显示
+     */
+    private Long isShowGps;
+
+    /**
+     * 折扣率(可能为JSON或文本)
+     */
+    //@NotNull(message = "折扣率(可能为JSON或文本)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long discountRate;
+
+    /**
+     * 拼音码(用于快速检索)
+     */
+    //@NotBlank(message = "拼音码(用于快速检索)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String pyCode;
+
+    /**
+     * 分类描述
+     */
+    //@NotBlank(message = "分类描述不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String classDescription;
+
+    /**
+     * 数据来源
+     */
+    //@NotBlank(message = "数据来源不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String dataSource;
+
+    /**
+     * 自定义标签1
+     */
+    //@NotBlank(message = "自定义标签1不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLable1;
+
+    /**
+     * 自定义标签2
+     */
+    //@NotBlank(message = "自定义标签2不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLable2;
+
+    /**
+     * 自定义链接1
+     */
+    //@NotBlank(message = "自定义链接1不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLink1;
+
+    /**
+     * 自定义链接2
+     */
+    //@NotBlank(message = "自定义链接2不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String oneLink2;
+
+    /**
+     * 排序值,默认为0
+     */
+    //@NotNull(message = "排序值,默认为0不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long sort;
+
+    /**
+     * 审核人员id
+     */
+    //@NotNull(message = "审核人员id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long reviewerId;
+
+    /**
+     * 客户id
+     */
+    //@NotNull(message = "客户id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long customerId;
+
+    /**
+     * 颜色(如CSS颜色值)
+     */
+    //@NotBlank(message = "颜色(如CSS颜色值)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String color;
+
+    /**
+     * 采购编号
+     */
+    //@NotBlank(message = "采购编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseNo;
+
+    /**
+     * 采购名称
+     */
+    //@NotBlank(message = "采购名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseName;
+
+    /**
+     * 采购负责人编号
+     */
+    //@NotBlank(message = "采购负责人编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseManagerNo;
+
+    /**
+     * 采购负责人姓名
+     */
+    //@NotBlank(message = "采购负责人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String purchaseManagerName;
+
+    /**
+     * 所属平台(0=Web, 1=小程序)
+     */
+    //@NotNull(message = "所属平台(0=Web, 1=小程序)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long platform;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 52 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductClassificationDiyBo.java

@@ -0,0 +1,52 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ProductClassificationDiy;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 商品自定义属性业务对象 product_classification_diy
+ *
+ * @author LionLi
+ * @date 2026-04-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ProductClassificationDiy.class, reverseConvertGenerate = false)
+public class ProductClassificationDiyBo extends BaseEntity {
+
+    /**
+     *
+     */
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    //@NotNull(message = "商品id不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long productId;
+
+    /**
+     * 属性key
+     */
+    //@NotBlank(message = "属性key不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String attributeKey;
+
+    /**
+     * 属性value
+     */
+    private String attributeValue;
+
+    /**
+     * 备注
+     */
+    //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String remark;
+
+
+}

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductPoolAuditBo.java

@@ -97,6 +97,11 @@ public class ProductPoolAuditBo extends BaseEntity {
      * */
     private List<ProductItem> products;
 
+    /**
+     * 申请类型 0更新,1移出
+     * */
+    private Integer applyType;
+
     /**
      * 产品项
      * */

+ 13 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductPoolLinkAuditBo.java

@@ -87,6 +87,19 @@ public class ProductPoolLinkAuditBo extends BaseEntity {
     //@NotBlank(message = "备注不能为空", groups = { AddGroup.class, EditGroup.class })
     private String remark;
 
+    /**
+     * 申请类型 0更新,1移出
+     * */
+    private Integer type;
+
+    /**
+//     * 计价规则(0 一品一价,1 按类目折扣率报价)
+     * */
+    private String pricingRule;
+    /**
+     * 起订量
+     * */
+    private Long minOrderQuantity;
 
 
 }

+ 93 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseAuditVo.java

@@ -0,0 +1,93 @@
+package org.dromara.product.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.product.domain.ProductBaseAudit;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 商品审核视图对象 product_base_audit
+ *
+ * @author LionLi
+ * @date 2026-04-06
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ProductBaseAudit.class)
+public class ProductBaseAuditVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     * 商品id
+     */
+    @ExcelProperty(value = "商品id")
+    private Long productId;
+
+    /**
+     * 审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回,4=营销审核,5运营审核
+     */
+    @ExcelProperty(value = "审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回,4=营销审核,5运营审核")
+    private Long auditStatus;
+
+    /**
+     * 审核原因
+     */
+    @ExcelProperty(value = "审核原因")
+    private String auditReason;
+
+    /**
+     * 审核人
+     */
+    @ExcelProperty(value = "审核人")
+    private Long auditUserId;
+
+    /**
+     * 审核时间
+     */
+    @ExcelProperty(value = "审核时间")
+    private Date auditTime;
+
+    /**
+     * 商品审核数据
+     */
+    @ExcelProperty(value = "商品审核数据")
+    private String productData;
+
+    /**
+     * 类型 0=提交审核,1上下架审核
+     */
+    @ExcelProperty(value = "类型 0=提交审核,1上下架审核")
+    private Long type;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+    /**
+    * 商品数据
+    * */
+    private ProductBaseVo productBaseVo;
+
+
+}

+ 20 - 17
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java

@@ -10,11 +10,13 @@ import org.dromara.common.excel.annotation.ExcelDictFormat;
 import org.dromara.common.excel.convert.ExcelDictConvert;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import org.dromara.product.domain.ProductClassificationDiy;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 
 /**
@@ -247,7 +249,7 @@ public class ProductBaseVo implements Serializable {
      * UPC(S)条码
      */
     @ExcelProperty(value = "UPC(S)条码")
-    private String upcBarcode;
+    private String barCoding;
 
     /**
      * 发票名称
@@ -259,7 +261,7 @@ public class ProductBaseVo implements Serializable {
      * 发票规格
      */
     @ExcelProperty(value = "发票规格")
-    private String invoiceSpec;
+    private String invoiceSpecs;
 
     /**
      * 包装规格
@@ -277,7 +279,7 @@ public class ProductBaseVo implements Serializable {
      * 商品重量
      */
     @ExcelProperty(value = "商品重量")
-    private String weight;
+    private String productWeight;
 
     /**
      * 重量单位
@@ -289,7 +291,7 @@ public class ProductBaseVo implements Serializable {
      * 商品体积
      */
     @ExcelProperty(value = "商品体积")
-    private String volume;
+    private String productVolume;
 
     /**
      * 体积单位
@@ -357,17 +359,12 @@ public class ProductBaseVo implements Serializable {
     @ExcelProperty(value = "套证价")
     private BigDecimal certificatePrice;
 
-    /**
-     * 采购价
-     */
-    @ExcelProperty(value = "采购价")
-    private BigDecimal purchasePrice;
 
     /**
-     * 暂估采购价
+     * 最高采购价
      */
-    @ExcelProperty(value = "暂估采购价")
-    private BigDecimal estimatedPurchasePrice;
+    @ExcelProperty(value = "最高采购价")
+    private BigDecimal maxPurchasePrice;
 
     /**
      * 产品经理
@@ -420,7 +417,7 @@ public class ProductBaseVo implements Serializable {
     /**
      * 是否可定制 0:不可定制 1:可定制
      * */
-    private Long isCustomize;
+    private String isCustomize;
 
     /**
      * 总库存
@@ -436,10 +433,6 @@ public class ProductBaseVo implements Serializable {
      * */
     private Long virtualInventory;
 
-    /**
-     * 是否可定制
-     */
-    private Boolean customizable;
 
     /**
      * 定制说明
@@ -461,6 +454,11 @@ public class ProductBaseVo implements Serializable {
      */
     private String attributesList;
 
+    /**
+     * diy商品属性
+     * */
+    private List<ProductClassificationDiy> diyAttributesList;
+
     /**
      * 销售量/销量人气
      */
@@ -538,4 +536,9 @@ public class ProductBaseVo implements Serializable {
     * 产品池审核商品id
     * */
     private Long poolAuditProductId;
+
+    /**
+    * 供应商id
+    * */
+    private String supplierNo;
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно