Ver Fonte

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	yami-shop-api/src/main/resources/application-prod.yml
#	yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderServiceImpl.java
wangming há 1 dia atrás
pai
commit
deb0c8e375
37 ficheiros alterados com 884 adições e 259 exclusões
  1. 0 1
      yami-shop-api/src/main/java/com/yami/shop/api/controller/MyOrderController.java
  2. 13 0
      yami-shop-api/src/main/java/com/yami/shop/api/controller/OrderController.java
  3. 55 0
      yami-shop-api/src/main/java/com/yami/shop/api/controller/PopupConfigController.java
  4. 5 0
      yami-shop-api/src/main/resources/application-dev.yml
  5. 3 1
      yami-shop-api/src/main/resources/application-prod.yml
  6. 2 2
      yami-shop-api/src/main/resources/application.yml
  7. 116 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/model/ChannelProdRecord.java
  8. 12 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/model/OrderItem.java
  9. 39 1
      yami-shop-bean/src/main/java/com/yami/shop/bean/model/ShopSku.java
  10. 71 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/po/ProductPageQuery.java
  11. 11 8
      yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ChannelProdExportVO.java
  12. 14 7
      yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ChannelProdImportVO.java
  13. 19 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/vo/PopupConfigVO.java
  14. 29 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ProdChannelVO.java
  15. 102 0
      yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ProductPageVO.java
  16. 0 2
      yami-shop-platform/src/main/java/com/yami/shop/platform/controller/OrderController.java
  17. 5 2
      yami-shop-platform/src/main/java/com/yami/shop/platform/controller/ShopSkuController.java
  18. 2 2
      yami-shop-platform/src/main/resources/application.yml
  19. 2 1
      yami-shop-security/yami-shop-security-api/src/main/java/com/yami/shop/security/api/config/ResourceServerConfiguration.java
  20. 1 0
      yami-shop-security/yami-shop-security-platform/src/main/java/com/yami/shop/security/platform/config/ResourceServerConfiguration.java
  21. 2 2
      yami-shop-service/src/main/java/com/yami/shop/dao/ChannelProdMapper.java
  22. 7 0
      yami-shop-service/src/main/java/com/yami/shop/dao/OrderItemMapper.java
  23. 6 5
      yami-shop-service/src/main/java/com/yami/shop/dao/ShopSkuMapper.java
  24. 4 2
      yami-shop-service/src/main/java/com/yami/shop/service/ShopSkuService.java
  25. 3 3
      yami-shop-service/src/main/java/com/yami/shop/service/hb/impl/HBFrontCategoryService.java
  26. 0 2
      yami-shop-service/src/main/java/com/yami/shop/service/hb/impl/HBGoodsService.java
  27. 4 7
      yami-shop-service/src/main/java/com/yami/shop/service/impl/ChannelProdServiceImpl.java
  28. 0 66
      yami-shop-service/src/main/java/com/yami/shop/service/impl/ExportTaskServiceImpl.java
  29. 1 3
      yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderRefundServiceImpl.java
  30. 180 84
      yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderServiceImpl.java
  31. 0 5
      yami-shop-service/src/main/java/com/yami/shop/service/impl/PointsFailureRecordServiceImpl.java
  32. 21 12
      yami-shop-service/src/main/java/com/yami/shop/service/impl/ShopSkuServiceImpl.java
  33. 38 2
      yami-shop-service/src/main/java/com/yami/shop/utils/ExportUtils.java
  34. 2 2
      yami-shop-service/src/main/resources/mapper/ChannelProdMapper.xml
  35. 12 1
      yami-shop-service/src/main/resources/mapper/OrderItemMapper.xml
  36. 1 1
      yami-shop-service/src/main/resources/mapper/OrderMapper.xml
  37. 102 35
      yami-shop-service/src/main/resources/mapper/ShopSkuMapper.xml

+ 0 - 1
yami-shop-api/src/main/java/com/yami/shop/api/controller/MyOrderController.java

@@ -368,7 +368,6 @@ public class MyOrderController {
     @ApiOperation(value = "根据订单号确认收货", notes = "根据订单号确认收货")
     public ResponseEntity<String> receipt(@PathVariable("orderNumber") String orderNumber) {
         String userId = SecurityUtils.getUser().getUserId();
-//        String userId = "36726893042d492aba446439c5f00584";
         Order order = orderService.getOrderByOrderNumberAndUserId(orderNumber, userId, true);
         if (Objects.equals(order.getDvyType(), 1)) {
             CullenUtils.validateDataThrowException(Objects.equals(order.getHbOrderStatus(), 0), "订单未支付");

+ 13 - 0
yami-shop-api/src/main/java/com/yami/shop/api/controller/OrderController.java

@@ -70,6 +70,13 @@ public class OrderController {
     private IHBOrderService hbOrderService;
     @Autowired
     private ShopSkuMapper shopSkuMapper;
+    @Autowired
+    private SysConfigService sysConfigService;
+
+    /**
+     * 弹窗开关配置key
+     */
+    private static final String POPUP_SWITCH = "POPUP_SWITCH";
 
     /**
      * 生成订单
@@ -77,6 +84,12 @@ public class OrderController {
     @PostMapping("/confirm")
     @ApiOperation(value = "结算,生成订单信息", notes = "传入下单所需要的参数进行下单")
     public ResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) {
+        // 检查弹窗开关,如果开启则暂停下单
+        String popupSwitch = sysConfigService.getValue(POPUP_SWITCH);
+        if ("true".equalsIgnoreCase(popupSwitch)) {
+            throw new GlobalException("春节期间暂停下单,感谢您的理解!");
+        }
+
         if (orderParam.getShopId() == null) {
 //            orderParam.setShopId(1L);
             throw new GlobalException("请选择店铺!");

+ 55 - 0
yami-shop-api/src/main/java/com/yami/shop/api/controller/PopupConfigController.java

@@ -0,0 +1,55 @@
+package com.yami.shop.api.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.yami.shop.bean.vo.PopupConfigVO;
+import com.yami.shop.service.SysConfigService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 弹窗配置接口
+ */
+@RestController
+@RequestMapping("/popup")
+@Api(tags = "弹窗配置接口")
+@AllArgsConstructor
+public class PopupConfigController {
+
+    private final SysConfigService sysConfigService;
+
+    /**
+     * 弹窗开关配置key
+     */
+    private static final String POPUP_SWITCH = "POPUP_SWITCH";
+
+    /**
+     * 弹窗图片地址配置key
+     */
+    private static final String POPUP_IMAGE_URL = "POPUP_IMAGE_URL";
+
+    /**
+     * 获取弹窗配置
+     *
+     * @return 弹窗配置信息
+     */
+    @GetMapping("/config")
+    @ApiOperation(value = "获取弹窗配置", notes = "获取弹窗开关和图片地址配置")
+    public ResponseEntity<PopupConfigVO> getPopupConfig() {
+        PopupConfigVO vo = new PopupConfigVO();
+
+        // 获取弹窗开关配置
+        String switchValue = sysConfigService.getValue(POPUP_SWITCH);
+        vo.setShowPopup(StrUtil.isNotBlank(switchValue) && Boolean.parseBoolean(switchValue));
+
+        // 获取弹窗图片地址配置
+        String imageUrl = sysConfigService.getValue(POPUP_IMAGE_URL);
+        vo.setImageUrl(StrUtil.isBlank(imageUrl) ? "" : imageUrl);
+
+        return ResponseEntity.ok(vo);
+    }
+}

+ 5 - 0
yami-shop-api/src/main/resources/application-dev.yml

@@ -25,3 +25,8 @@ hb:
   host: https://p-open.hiboos.com
   appId: 5347a7077e65428bb9a87510ca7e1ea1
   secret: 67899367b17e4a8d8a7d10ebe8449b90
+smqjh:
+  #  pms-url: http://47.109.39.185:8080/smqjh-pms/api/v1/sync
+  #  pms-url: http://192.168.1.242:8080/smqjh-pms/api/v1/sync
+  pms-url: https://smqjh.api.zswlgz.com/smqjh-pms/api/v1/sync
+  omsBaseUrl: https://smqjh.api.zswlgz.com/smqjh-oms

+ 3 - 1
yami-shop-api/src/main/resources/application-prod.yml

@@ -26,5 +26,7 @@ hb:
   secret: f655f69f962f427db1f0436fd34cd998
 
 smqjh:
+  #  pms-url: http://47.109.39.185:8080/smqjh-pms/api/v1/sync
+  #  pms-url: http://192.168.1.242:8080/smqjh-pms/api/v1/sync
   pms-url: https://smqjh.api.zswlgz.com/smqjh-pms/api/v1/sync
-  omsBaseUrl: https://smqjh.api.zswlgz.com/smqjh-oms
+  omsBaseUrl: https://smqjh.api.zswlgz.com/smqjh-oms

+ 2 - 2
yami-shop-api/src/main/resources/application.yml

@@ -2,8 +2,8 @@
 spring:
   # 环境 dev|prod|docker
   profiles:
-    active: dev
-#    active: prod
+#    active: dev
+    active: prod
   #文件上传设置
   servlet:
     multipart:

+ 116 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/model/ChannelProdRecord.java

@@ -0,0 +1,116 @@
+package com.yami.shop.bean.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 导入价格记录实体类
+ * @author [您的姓名] on 2024/01/01
+ */
+@Data
+@TableName("tz_channel_prod_record")
+public class ChannelProdRecord implements java.io.Serializable{
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 充值编号
+     */
+    private String code;
+
+    /**
+     * 任务名称
+     */
+    private String name;
+
+    /**
+     * 渠道(企业ID)
+     */
+    private Long channelId;
+
+    /**
+     * 渠道名称
+     */
+    private String channelName;
+
+    /**
+     * 商品ID
+     */
+    private Long skuId;
+    /**
+     * 海博商品ID
+     */
+    private String hbSkuId;
+
+    /**
+     * 商品名称
+     */
+    private String skuName;
+
+    /**
+     * 商户ID
+     */
+    private Long shopId;
+
+    /**
+     * 商户名称
+     */
+    private String shopName;
+
+    /**
+     * 业务类型
+     */
+    private String businessType;
+
+    /**
+     * 进货价
+     */
+    private BigDecimal purchasePrice;
+
+    /**
+     * 出货价
+     */
+    private BigDecimal deliveryPrice;
+
+    /**
+     * 渠道对应商品售价
+     */
+    private BigDecimal channelProdPrice;
+
+    /**
+     * 状态(1-成功,0-失败)
+     */
+    private Integer status;
+
+    /**
+     * 失败原因
+     */
+    private String reasonForFailure;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 操作人
+     */
+    private String createBy;
+
+    /**
+     * 操作人姓名
+     */
+    private String createName;
+
+}

+ 12 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/model/OrderItem.java

@@ -205,4 +205,16 @@ public class OrderItem implements Serializable {
     @TableField(exist = false)
     private String spec;
 
+    /**
+     * 海博商品ID
+     */
+    @TableField(exist = false)
+    private String hbSkuId;
+
+    /**
+     * 商品编码
+     */
+    @TableField(exist = false)
+    private String skuCode;
+
 }

+ 39 - 1
yami-shop-bean/src/main/java/com/yami/shop/bean/model/ShopSku.java

@@ -13,11 +13,13 @@ package com.yami.shop.bean.model;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.experimental.Accessors;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -39,8 +41,44 @@ public class ShopSku implements Serializable {
 
     @TableField(exist = false)
     private String shopName;
+
+    /**
+     * 商品编码
+     */
+    @TableField(exist = false)
+    private String skuCode;
+    /**
+     * 海博商品ID
+     */
+    @TableField(exist = false)
+    private String hbSkuId;
+    /**
+     * 商品名称
+     */
     @TableField(exist = false)
     private String skuName;
+    /**
+     * 开始时间
+     */
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private String startTime;
+    /**
+     * 结束时间
+     */
+    @TableField(exist = false)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private String endTime;
+    /**
+     * 最大价格
+     */
+    @TableField(exist = false)
+    private BigDecimal maxPrice;
+    /**
+     * 最小价格
+     */
+    @TableField(exist = false)
+    private BigDecimal minPrice;
 
     /**
      * 单品ID
@@ -82,7 +120,6 @@ public class ShopSku implements Serializable {
      */
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date recTime;
-
     /**
      * 渠道商品
      */
@@ -93,4 +130,5 @@ public class ShopSku implements Serializable {
      */
     @TableField(exist = false)
     private Sku sku;
+
 }

+ 71 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/po/ProductPageQuery.java

@@ -0,0 +1,71 @@
+package com.yami.shop.bean.po;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+/**
+ * 品牌分页列表查询对象
+ *
+ * @author haoxr
+ * @since 2021/7/11
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProductPageQuery{
+
+    /**
+     * 海博商品编码
+     */
+    private String skuCode;
+    /**
+     * 海博商品ID
+     */
+    private String hbSkuId;
+    /**
+     * 商品规格名称
+     */
+    private String skuName;
+
+    /**
+     * 商品名称/统一id也可以业务系统id
+     */
+    private String keywords;
+
+    /**
+     * 上架状态(0:商家下架、1:上架、2:违规下架、3:平台审核)
+     */
+    private Integer status = null;
+
+
+    /**
+     * 开始时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private String startTime;
+
+    /**
+     * 结束时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private String endTime;
+
+    /**
+     * 最大价格
+     */
+    private BigDecimal maxPrice;
+    /**
+     * 最小价格
+     */
+    private BigDecimal minPrice;
+
+    /**
+     * 门店id
+     */
+    private Long shopId;
+
+}

+ 11 - 8
yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ChannelProdExportVO.java

@@ -13,31 +13,34 @@ import java.math.BigDecimal;
 @Data
 public class ChannelProdExportVO {
 
-    @ExcelProperty(value = "海博商品ID*", index = 0)
+    @ExcelProperty(value = "海博商品规格ID", index = 0)
     @ColumnWidth(20)
-    private Long skuId;
+    private Long hbSkuId;
 
-    @ExcelProperty(value = "商品名称", index = 1)
+    @ExcelProperty(value = "商品规格名称", index = 1)
     @ColumnWidth(40)
     private String skuName;
 
-    @ExcelProperty(value = "门店名称*", index = 3)
+    @ExcelProperty(value = "门店名称", index = 2)
     @ColumnWidth(20)
     private String shopName;
+    @ExcelProperty(value = "门店商品库存", index = 3)
+    @ColumnWidth(20)
+    private Integer shopSkuStock;
 
-    @ExcelProperty(value = "销售渠道*", index = 2)
+    @ExcelProperty(value = "销售渠道", index = 4)
     @ColumnWidth(20)
     private String channelName;
 
-    @ExcelProperty(value = "进货价(元)", index = 4)
+    @ExcelProperty(value = "进货价(元)", index = 5)
     @ColumnWidth(20)
     private BigDecimal purchasePrice;
 
-    @ExcelProperty(value = "出货价(元)", index = 5)
+    @ExcelProperty(value = "出货价(元)", index = 6)
     @ColumnWidth(20)
     private BigDecimal deliveryPrice;
 
-    @ExcelProperty(value = "渠道售价(元)*", index = 6)
+    @ExcelProperty(value = "渠道售价(元)", index = 7)
     @ColumnWidth(20)
     private BigDecimal channelProdPrice;
 

+ 14 - 7
yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ChannelProdImportVO.java

@@ -17,36 +17,43 @@ import java.math.BigDecimal;
 @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 9) // 内容背景色(9=淡黄色)
 public class ChannelProdImportVO {
 
-    @ExcelProperty(value = "海博商品ID*", index = 0)
+
+    @ExcelProperty(value = "海博商品ID", index = 0)
     @ColumnWidth(20) // 列宽
     @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 居中对齐
     private String skuId;
 
-    @ExcelProperty(value = "商品名称", index = 1)
+    @ExcelProperty(value = "海博商品编码", index = 1)
+    @ColumnWidth(20) // 列宽
+    @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER) // 居中对齐
+    private String skuCode;
+
+    @ExcelProperty(value = "商品名称", index = 2)
     @ColumnWidth(40)
     @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
     private String skuName;
 
-    @ExcelProperty(value = "销售渠道*", index = 2)
+    @ExcelProperty(value = "销售渠道*", index = 3)
     @ColumnWidth(20)
     @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
     private String channelName;
 
-    @ExcelProperty(value = "门店名称*", index = 3)
+    @ExcelProperty(value = "门店名称*", index = 4)
     @ColumnWidth(20)
     @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
     private String shopName;
 
-    @ExcelProperty(value = "进货价(元)", index = 4)
+    @ExcelProperty(value = "进货价(元)", index = 5)
     @ColumnWidth(20)
     private BigDecimal purchasePrice;
 
-    @ExcelProperty(value = "出货价(元)", index = 5)
+    @ExcelProperty(value = "出货价(元)", index = 6)
     @ColumnWidth(20)
     private BigDecimal deliveryPrice;
 
-    @ExcelProperty(value = "渠道售价(元)*", index = 6)
+    @ExcelProperty(value = "渠道售价(元)*", index = 7)
     @ColumnWidth(20)
     private BigDecimal channelProdPrice;
 
+
 }

+ 19 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/vo/PopupConfigVO.java

@@ -0,0 +1,19 @@
+package com.yami.shop.bean.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 弹窗配置VO
+ */
+@Data
+@ApiModel("弹窗配置")
+public class PopupConfigVO {
+
+    @ApiModelProperty("是否显示弹窗")
+    private Boolean showPopup;
+
+    @ApiModelProperty("弹窗图片地址")
+    private String imageUrl;
+}

+ 29 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ProdChannelVO.java

@@ -0,0 +1,29 @@
+package com.yami.shop.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 商品企业价格出参对象
+ */
+@Data
+public class ProdChannelVO {
+    /** 企业ID */
+    private Long channelId;
+    /** 企业名称 */
+    private String channelName;
+
+    /** 企业等级 */
+    private String level;
+    /** 门店名称 */
+    private String shopName;
+    /**更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    /** 企业对应价格 */
+    private BigDecimal price;
+}

+ 102 - 0
yami-shop-bean/src/main/java/com/yami/shop/bean/vo/ProductPageVO.java

@@ -0,0 +1,102 @@
+package com.yami.shop.bean.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.yami.shop.bean.model.Sku;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author fbj
+ * 商品分页出参对象
+ */
+@Data
+public class ProductPageVO {
+
+    /**
+     * 统一id
+     */
+    private String supId;
+
+    /**
+     * 商品ID
+     */
+    private Long spuId;
+
+    /**
+     * 海博hbSpuId
+     */
+    private String hbSpuId;
+    /**
+     * 海博skuId
+     */
+    private String hbSkuId;
+    /**
+     * 商品编码
+     */
+    private String skuCode;
+
+    /**
+     * 商品图片
+     */
+    private String pic;
+
+    /**
+     * 商品名称
+     */
+    private String prodName;
+    /**
+     * 商品规格名称
+     */
+    private String skuName;
+    /**
+     * 业务类型
+     */
+    private String channelCode;
+
+    /**
+     * 商户ID
+     */
+    private Long shopId;
+    /**
+     * 商户
+     */
+    private String shopName;
+
+    /**
+     * 商品规格ID
+     */
+    private Long skuId;
+
+    /**
+     * 库存
+     */
+    private Integer shopSkuStocks;
+
+    /**
+     * 上架状态(0:商家下架、1:上架、2:违规下架、3:平台审核)
+     */
+    private Integer status;
+
+    /**
+     * 更新时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+    /**
+     * 商品企业价格
+     */
+    private List<ProdChannelVO> channelVOS;
+
+    /**
+     * 商品信息
+     */
+    private Sku sku;
+    /**
+     * 价格
+     */
+    private BigDecimal price;
+
+}

+ 0 - 2
yami-shop-platform/src/main/java/com/yami/shop/platform/controller/OrderController.java

@@ -156,10 +156,8 @@ public class OrderController {
         //子订单数据处理
         List<Order> list = orderService.list(new LambdaUpdateWrapper<Order>().eq(Order::getParentOrderNumber, orderNumber)
                 .eq(Order::getDeleteStatus, 0));
-
         if (ObjectUtil.isNotEmpty(list)) {
             for (Order order1 : list) {
-
                 List<OrderItem> orderItems2 = orderItemService.getOrderItemsByOrderNumber(orderNumber);
                 if (!orderItems2.isEmpty()) {
                     orderItems2.forEach(c -> {

+ 5 - 2
yami-shop-platform/src/main/java/com/yami/shop/platform/controller/ShopSkuController.java

@@ -11,11 +11,14 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yami.shop.bean.dto.OrderRefundDto;
 import com.yami.shop.bean.model.ChannelProd;
 import com.yami.shop.bean.model.ShopSku;
+import com.yami.shop.bean.po.ProductPageQuery;
+import com.yami.shop.bean.vo.ProductPageVO;
 import com.yami.shop.common.util.PageParam;
 import com.yami.shop.common.util.R;
 import com.yami.shop.service.ShopSkuService;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -47,14 +50,14 @@ public class ShopSkuController {
      * 分页查询门店对应商品详细
      */
     @GetMapping("/page")
-    public R<IPage<ShopSku>> page(PageParam<ShopSku> page, ShopSku shopSku) {
+    public R<IPage<ProductPageVO>> page(PageParam<ProductPageQuery> page,  @Param("shopSku") ProductPageQuery shopSku) {
         return R.SUCCESS(shopProdService.shopSkuPage(page,shopSku));
     }
 
 
     @GetMapping("/export")
     @ApiOperation(value = "导出渠道商品数据")
-    public void exportChannelProds(ShopSku shopSku, HttpServletResponse response) {
+    public void exportChannelProds(ProductPageQuery shopSku, HttpServletResponse response) {
         shopProdService.exportChannelProds(shopSku, response);
     }
 

+ 2 - 2
yami-shop-platform/src/main/resources/application.yml

@@ -1,8 +1,8 @@
 spring:
   # 环境 dev|prod|docker quartz定时任务
   profiles:
-    active: dev
-#    active: prod
+#    active: dev
+    active: prod
   #文件上传设置
   servlet:
 

+ 2 - 1
yami-shop-security/yami-shop-security-api/src/main/java/com/yami/shop/security/api/config/ResourceServerConfiguration.java

@@ -51,7 +51,8 @@ public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
                         "/p/order/**",
                         "/p/user/miniAppLogin",
                         "/p/prodComm/commList",
-                        "/p/prodComm/commentCount"
+                        "/p/prodComm/commentCount",
+                        "/popup/**"
                         ).permitAll()
                 .and()
 

+ 1 - 0
yami-shop-security/yami-shop-security-platform/src/main/java/com/yami/shop/security/platform/config/ResourceServerConfiguration.java

@@ -61,6 +61,7 @@ public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
 
 //                    "/admin/enterprise/**",
 //                    "/admin/file/upload/img",
+                    "/shop/shopProd/**",
                     "/admin/enterprise/downloadXlsx",
                     "/admin/enterprise/downloadExcel",
                     "/admin/enterprise/downloadErrorExcel",

+ 2 - 2
yami-shop-service/src/main/java/com/yami/shop/dao/ChannelProdMapper.java

@@ -14,7 +14,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yami.shop.bean.dto.UpdateShannerProdDTO;
 import com.yami.shop.bean.model.ChannelProd;
-import com.yami.shop.bean.vo.ChannelProdExportVO;
+import com.yami.shop.bean.vo.ProdChannelVO;
 import com.yami.shop.common.util.PageParam;
 import org.apache.ibatis.annotations.Param;
 
@@ -94,7 +94,7 @@ public interface ChannelProdMapper extends BaseMapper<ChannelProd> {
      * @param shopId 商家ID
      * @return 渠道商品列表
      */
-    List<ChannelProd> selectListAll(@Param("skuId")Long skuId, @Param("shopId")Long shopId);
+    List<ProdChannelVO> selectListAll(@Param("skuId")Long skuId, @Param("shopId")Long shopId);
 
 
     /**

+ 7 - 0
yami-shop-service/src/main/java/com/yami/shop/dao/OrderItemMapper.java

@@ -40,6 +40,13 @@ public interface OrderItemMapper extends BaseMapper<OrderItem> {
      */
     OrderItem findBySkuIdAndOrderNumber(@Param("skuId")Long skuId,@Param("orderNumber") String orderNumber);
 
+    /**
+     * 批量查询订单项(用于导出优化)
+     * @param orderNumbers 订单编号列表
+     * @return 订单项列表
+     */
+    List<OrderItem> getListByOrderNumbers(@Param("orderNumbers") List<String> orderNumbers);
+
 //    List<OrderItem> getUnCloseRefundOrderItemByOrderNumber(String orderNumber);
 
 //	void insertBatch(List<OrderItem> orderItems);

+ 6 - 5
yami-shop-service/src/main/java/com/yami/shop/dao/ShopSkuMapper.java

@@ -12,9 +12,10 @@ package com.yami.shop.dao;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.yami.shop.bean.model.ChannelProd;
 import com.yami.shop.bean.model.ShopSku;
+import com.yami.shop.bean.po.ProductPageQuery;
 import com.yami.shop.bean.vo.ChannelProdExportVO;
+import com.yami.shop.bean.vo.ProductPageVO;
 import com.yami.shop.common.util.PageParam;
 import org.apache.ibatis.annotations.Param;
 
@@ -36,17 +37,17 @@ public interface ShopSkuMapper extends BaseMapper<ShopSku> {
     /**
      * 分页查询门店商品
      * @param page 分页参数
-     * @param shopSku 门店商品
+     * @param query 查询条件
      * @return 门店商品
      */
-    IPage<ShopSku> selectShopSkuPage(@Param("page")PageParam<ShopSku> page, @Param("shopSku")ShopSku shopSku);
+    IPage<ProductPageVO> selectShopSkuPage(@Param("page")PageParam<ProductPageQuery> page, @Param("query") ProductPageQuery query);
 
 
     /**
      * 导出渠道商品列表
-     * @param shopSku 查询条件
+     * @param query 查询条件
      * @return 渠道商品列表
      */
-    List<ChannelProdExportVO> exportList(@Param("shopSku")ShopSku shopSku);
+    List<ChannelProdExportVO> exportList(@Param("query")ProductPageQuery query);
 
 }

+ 4 - 2
yami-shop-service/src/main/java/com/yami/shop/service/ShopSkuService.java

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yami.shop.bean.model.ChannelProd;
 import com.yami.shop.bean.model.ShopSku;
+import com.yami.shop.bean.po.ProductPageQuery;
+import com.yami.shop.bean.vo.ProductPageVO;
 import com.yami.shop.common.util.PageParam;
 
 import javax.servlet.http.HttpServletResponse;
@@ -22,12 +24,12 @@ public interface ShopSkuService extends IService<ShopSku> {
      * @param shopSku 查询参数
      * @return 分页数据
      */
-    IPage<ShopSku> shopSkuPage(PageParam<ShopSku> page, ShopSku shopSku);
+    IPage<ProductPageVO> shopSkuPage(PageParam<ProductPageQuery> page, ProductPageQuery shopSku);
 
     /**
      * 导出门店渠道商品数据
      * @param response 查询参数
      * @param response 响应
      */
-    void exportChannelProds(ShopSku shopSku, HttpServletResponse response);
+    void exportChannelProds(ProductPageQuery shopSku, HttpServletResponse response);
 }

+ 3 - 3
yami-shop-service/src/main/java/com/yami/shop/service/hb/impl/HBFrontCategoryService.java

@@ -174,7 +174,7 @@ public class HBFrontCategoryService implements IHBFrontCategoryService {
 
         shopCategoryMapper.insert(shopCategory);
         try {
-            String syncUrl = smqjhUtil.getSmqjhPmsUrl() + "/syncShopCategoryData/";
+            String syncUrl = smqjhUtil.getSmqjhPmsUrl() + "/syncShopCategoryData";
             String response = com.yami.shop.common.util.HttpUtil.post(syncUrl, shopCategory);
             log.info("推送门店分类到同步服务器结果: {}", response);
         } catch (Exception e) {
@@ -211,7 +211,7 @@ public class HBFrontCategoryService implements IHBFrontCategoryService {
     public void deleteFrontCategory(JSONObject hbRequest) {
         JSONObject body = hbRequest.getJSONObject("body");
         JSONArray codeList = body.getJSONArray("codeList");
-        for (Object codeObject : codeList) {
+        for (Object codeObject : codeList) {    
             String code = codeObject.toString();
             log.info("前台类目删除,body:{}", code);
             FrontCategory frontCategory = frontCategoryMapper.selectOne(new LambdaQueryWrapper<FrontCategory>()
@@ -227,7 +227,7 @@ public class HBFrontCategoryService implements IHBFrontCategoryService {
             try {
                 List<ShopCategory> shopCategories = shopCategoryMapper.selectList(new LambdaQueryWrapper<ShopCategory>().eq(ShopCategory::getCode, code));
                 for (ShopCategory shopCategory : shopCategories) {
-                    String syncUrl = smqjhUtil.getSmqjhPmsUrl() + "/syncShopCategoryData/";
+                    String syncUrl = smqjhUtil.getSmqjhPmsUrl() + "/syncShopCategoryData";
                     String response = com.yami.shop.common.util.HttpUtil.post(syncUrl, shopCategory);
                     log.info("推送门店分类到同步服务器结果: {}", response);
                 }

+ 0 - 2
yami-shop-service/src/main/java/com/yami/shop/service/hb/impl/HBGoodsService.java

@@ -284,8 +284,6 @@ public class HBGoodsService implements IHBGoodsService {
                             .eq(FrontCategory::getCode, categoryProd.getCode()).eq(FrontCategory::getIsDelete, 0));
                     addShopCategory(frontCategory, categoryProd.getProdId(), shopDetail.getShopId(), shopDetail.getHbStationId());
                 }
-
-
             }
         } catch (Exception e) {
             log.error("商品失败:{}", e.getMessage(), e);

+ 4 - 7
yami-shop-service/src/main/java/com/yami/shop/service/impl/ChannelProdServiceImpl.java

@@ -3,20 +3,13 @@ package com.yami.shop.service.impl;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.excel.EasyExcel;
-import com.alipay.api.domain.Shop;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yami.shop.bean.dto.SetChannelPriceDto;
 import com.yami.shop.bean.dto.UpdateShannerProdDTO;
 import com.yami.shop.bean.model.*;
-import com.yami.shop.bean.vo.ChannelProdExportVO;
 import com.yami.shop.bean.vo.ChannelProdImportVO;
 import com.yami.shop.common.exception.GlobalException;
-import com.yami.shop.common.exception.YamiShopBindException;
-import com.yami.shop.common.util.PageParam;
-import com.yami.shop.common.util.SpringContextUtils;
 import com.yami.shop.dao.*;
 import com.yami.shop.service.ChannelProdService;
 import lombok.AllArgsConstructor;
@@ -269,6 +262,7 @@ public class ChannelProdServiceImpl extends ServiceImpl<ChannelProdMapper, Chann
                 channelProd.setDeliveryPrice(importVO.getDeliveryPrice());
                 channelProd.setChannelProdPrice(importVO.getChannelProdPrice());
                 channelProd.setRecTime(new Date());
+                channelProd.setUpdateTime(new Date());
 
                 //检查门店是否存在
                 ShopDetail shopDetail = shopDetailMapper.selectOne(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopName, importVO.getShopName()));
@@ -332,6 +326,8 @@ public class ChannelProdServiceImpl extends ServiceImpl<ChannelProdMapper, Chann
                 channelProd.setDeliveryPrice(updateShannerProdDTO.getDeliveryPrice());
                 channelProd.setChannelProdPrice(setChannelPriceDto.getChannelProdPrice());
                 channelProd.setRecTime(new Date());
+                channelProd.setIsDelete(0);
+                channelProd.setUpdateTime(new Date());
                 channelProdMapper.insert(channelProd);
 
                 //检查门店是否已存在
@@ -344,6 +340,7 @@ public class ChannelProdServiceImpl extends ServiceImpl<ChannelProdMapper, Chann
                     channelShop.setIsDelete(0);
                     channelShop.setChannelId(setChannelPriceDto.getChannelId());
                     channelShop.setShopId(updateShannerProdDTO.getShopId());
+                    channelProd.setUpdateTime(new Date());
                     channelShopMapper.insert(channelShop);
                     log.info("添加渠道门店关联数据成功");
                 }

+ 0 - 66
yami-shop-service/src/main/java/com/yami/shop/service/impl/ExportTaskServiceImpl.java

@@ -1,90 +1,31 @@
-/*
- * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
- *
- * https://www.gz-yami.com/
- *
- * 未经允许,不可做商业用途!
- *
- * 版权所有,侵权必究!
- */
 
 package com.yami.shop.service.impl;
 
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.date.DateTime;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.lang.Snowflake;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.RandomUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.poi.excel.ExcelUtil;
-import cn.hutool.poi.excel.ExcelWriter;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import com.google.gson.JsonObject;
-import com.google.gson.internal.LinkedTreeMap;
-import com.yami.shop.bean.app.dto.OrderCountData;
-import com.yami.shop.bean.app.dto.ShopCartOrderMergerDto;
-import com.yami.shop.bean.dto.hb.HBBaseReq;
 import com.yami.shop.bean.enums.*;
-import com.yami.shop.bean.event.CancelOrderEvent;
-import com.yami.shop.bean.event.ReceiptOrderEvent;
-import com.yami.shop.bean.event.SubmitOrderEvent;
-import com.yami.shop.bean.event.SubmitScoreOrderEvent;
 import com.yami.shop.bean.model.*;
 import com.yami.shop.bean.param.*;
 import com.yami.shop.bean.vo.ExportContext;
 import com.yami.shop.bean.vo.ExportTaskVo;
-import com.yami.shop.bean.vo.OrderCountVo;
-import com.yami.shop.common.config.Constant;
 import com.yami.shop.common.exception.GlobalException;
-import com.yami.shop.common.util.Arith;
-import com.yami.shop.common.util.PageAdapter;
 import com.yami.shop.common.util.PageParam;
 import com.yami.shop.common.util.R;
 import com.yami.shop.dao.*;
 import com.yami.shop.service.ExportTaskService;
-import com.yami.shop.service.OrderItemService;
-import com.yami.shop.service.OrderService;
-import com.yami.shop.service.OrderSettlementService;
-import com.yami.shop.utils.CullenUtils;
 import com.yami.shop.utils.ExportUtils;
-import com.yami.shop.utils.HBSignUtil;
-import com.yami.shop.wx.po.RefundInfoPo;
-import com.yami.shop.wx.service.WxProviderService;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.xssf.usermodel.XSSFWorkbook;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.support.TransactionTemplate;
 
-import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.net.URLEncoder;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
@@ -94,17 +35,10 @@ import java.nio.channels.WritableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.text.SimpleDateFormat;
 import java.time.Instant;
-import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.stream.Collectors;
-
-import static com.yami.shop.common.util.HttpUtil.post;
 
 /**
  * @author lgh on 2018/09/15.

+ 1 - 3
yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderRefundServiceImpl.java

@@ -1194,9 +1194,7 @@ public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, Order
             }
 
             if (applyDeal == 1) {
-                if (ChannelType.SMQJH.value().equals(orderRefund.getChannelType())) {
-
-                } else {
+                if (!ChannelType.SMQJH.value().equals(orderRefund.getChannelType())) {
                     //订单退款金额或者积分处理
                     orderService.returnRefund(orderRefund.getOrderNumber());
                 }

+ 180 - 84
yami-shop-service/src/main/java/com/yami/shop/service/impl/OrderServiceImpl.java

@@ -62,10 +62,7 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.streaming.SXSSFSheet;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.springframework.beans.BeanUtils;
@@ -868,6 +865,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     @Transactional(rollbackFor = Exception.class)
     public void receiptOrder(List<Order> orders) {
         orderMapper.receiptOrder(orders);
+        log.info("用户确认收货,订单号:{}", orders.stream().map(Order::getOrderNumber).collect(Collectors.joining(",")));
         for (Order order : orders) {
             eventPublisher.publishEvent(new ReceiptOrderEvent(order));
         }
@@ -890,10 +888,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                 List<OrderItem> orderItems = orderItemMapper.getListByOrderNumber(c.getOrderNumber());
                 c.setOrderItems(orderItems);
                 c.setGoodsTotalCount(orderItems.stream().map(OrderItem::getProdCount).reduce(0, Integer::sum));
-                if (c.getReceiver() == null){
+                if(c.getAddrOrderId() != null) {
                     c.setReceiver(c.getConsigneeName());
-                }
-                if (c.getUserMobile() == null){
                     c.setUserMobile(c.getConsigneeMobile());
                 }
             });
@@ -1935,16 +1931,26 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         @Override
         public R<String> export (BackendOrderParam orderParam, Long userId) {
             List<Order> orderList = orderMapper.findList(orderParam);
-            if (!orderList.isEmpty()) {
-                orderList.forEach(c -> {
-                    List<OrderItem> orderItems = orderItemMapper.getListByOrderNumber(c.getOrderNumber());
-                    c.setOrderItems(orderItems);
-                    c.setGoodsTotalCount(orderItems.stream().map(OrderItem::getProdCount).reduce(0, Integer::sum));
-                });
-            }
             if (orderList.isEmpty()) {
                 return R.FAIL("未查询到数据不允许导出");
             }
+            
+            // 性能优化:批量查询所有订单项,避免N+1查询问题
+            List<String> orderNumbers = orderList.stream()
+                    .map(Order::getOrderNumber)
+                    .collect(Collectors.toList());
+            List<OrderItem> allOrderItems = orderItemMapper.getListByOrderNumbers(orderNumbers);
+            
+            // 按订单编号分组
+            Map<String, List<OrderItem>> orderItemMap = allOrderItems.stream()
+                    .collect(Collectors.groupingBy(OrderItem::getOrderNumber));
+            
+            // 设置订单项
+            orderList.forEach(c -> {
+                List<OrderItem> orderItems = orderItemMap.getOrDefault(c.getOrderNumber(), Collections.emptyList());
+                c.setOrderItems(orderItems);
+                c.setGoodsTotalCount(orderItems.stream().map(OrderItem::getProdCount).reduce(0, Integer::sum));
+            });
             String taskId = UUID.randomUUID().toString();
             ExportTask exportTask = new ExportTask();
             exportTask.setUserId(userId);
@@ -2034,16 +2040,19 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 
                 String[] headers = {
                         "序号", "订单编号", "下单时间", "付款时间", "订单状态", "订单类型",
-                        "商品名称", "规格", "单价(元)", "数量", "小计(元)",
+                        "商品名称", "海博商品ID", "商品编码", "规格", "单价(元)", "数量", "小计(元)",
                         "商品总数量", "商品总额(元)", "运费(元)", "积分抵扣(元)",
                         "实付金额", "所属企业", "买家姓名", "买家电话"
                 };
                 // 创建合并单元格的表头
-                ExportUtils.createMergedHeader(sheet, headerStyle, "正常订单",18);
+                ExportUtils.createMergedHeader(sheet, headerStyle, "正常订单",20);
 
                 // 创建列标题行
                 ExportUtils.createColumnHeaders(sheet, headerStyle, headers);
 
+                // 计算并创建总计行
+                createSummaryRow(sheet, orderList, workbook);
+
                 // 填充数据
                 fillOrderData(sheet, orderList, dataStyle, numberStyle, dateStyle, context);
                 // 写入文件
@@ -2090,18 +2099,108 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
             sheet.setColumnWidth(4, 10 * 256);   // 订单状态
             sheet.setColumnWidth(5, 8 * 256);    // 订单类型
             sheet.setColumnWidth(6, 25 * 256);   // 商品名称
-            sheet.setColumnWidth(7, 20 * 256);   // 规格
-            sheet.setColumnWidth(8, 10 * 256);   // 单价
-            sheet.setColumnWidth(9, 8 * 256);    // 数量
-            sheet.setColumnWidth(10, 10 * 256);   // 小计
-            sheet.setColumnWidth(11, 12 * 256);  // 商品总数量
-            sheet.setColumnWidth(12, 12 * 256);  // 商品总额
-            sheet.setColumnWidth(13, 8 * 256);   // 运费
-            sheet.setColumnWidth(14, 12 * 256);  // 积分抵扣
-            sheet.setColumnWidth(15, 10 * 256);  // 实付金额
-            sheet.setColumnWidth(16, 15 * 256);  // 所属企业
-            sheet.setColumnWidth(17, 10 * 256);  // 买家姓名
-            sheet.setColumnWidth(18, 15 * 256);  // 买家电话
+            sheet.setColumnWidth(7, 15 * 256);   // 海博商品ID
+            sheet.setColumnWidth(8, 15 * 256);   // 商品编码
+            sheet.setColumnWidth(9, 20 * 256);   // 规格
+            sheet.setColumnWidth(10, 10 * 256);  // 单价
+            sheet.setColumnWidth(11, 8 * 256);   // 数量
+            sheet.setColumnWidth(12, 10 * 256);  // 小计
+            sheet.setColumnWidth(13, 12 * 256);  // 商品总数量
+            sheet.setColumnWidth(14, 12 * 256);  // 商品总额
+            sheet.setColumnWidth(15, 8 * 256);   // 运费
+            sheet.setColumnWidth(16, 12 * 256);  // 积分抵扣
+            sheet.setColumnWidth(17, 10 * 256);  // 实付金额
+            sheet.setColumnWidth(18, 15 * 256);  // 所属企业
+            sheet.setColumnWidth(19, 10 * 256);  // 买家姓名
+            sheet.setColumnWidth(20, 15 * 256);  // 买家电话
+        }
+
+        /**
+         * 创建总计行
+         */
+        private void createSummaryRow(Sheet sheet, List<Order> orderList, Workbook workbook) {
+            // 创建总计行样式(浅绿色背景)
+            CellStyle summaryStyle = workbook.createCellStyle();
+            summaryStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
+            summaryStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            summaryStyle.setBorderTop(BorderStyle.THIN);
+            summaryStyle.setBorderBottom(BorderStyle.THIN);
+            summaryStyle.setBorderLeft(BorderStyle.THIN);
+            summaryStyle.setBorderRight(BorderStyle.THIN);
+            summaryStyle.setAlignment(HorizontalAlignment.CENTER);
+            summaryStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+
+            // 创建总计行数字样式(浅绿色背景)
+            CellStyle summaryNumberStyle = workbook.createCellStyle();
+            summaryNumberStyle.cloneStyleFrom(summaryStyle);
+            DataFormat dataFormat = workbook.createDataFormat();
+            summaryNumberStyle.setDataFormat(dataFormat.getFormat("#,##0.00"));
+
+            // 计算总计值
+            int totalProductCount = 0;      // 商品总数量
+            double totalAmount = 0;         // 商品总额
+            double totalFreight = 0;        // 运费
+            double totalOffsetPoints = 0;   // 积分抵扣
+            double totalActualAmount = 0;   // 实付金额
+
+            for (Order order : orderList) {
+                for (OrderItem item : order.getOrderItems()) {
+                    // 商品总数量(每行的商品数量)
+                    totalProductCount += item.getProdCount() != null ? item.getProdCount() : 0;
+                    
+                    // 商品总额(每行单独计算,使用当前商品的小计金额)
+                    if (item.getProductTotalAmount() != null) {
+                        totalAmount += item.getProductTotalAmount();
+                    }
+                    
+                    // 运费(按商品数量比例分摊)
+                    if (order.getFreightAmount() != null && order.getProductNums() > 0) {
+                        totalFreight += Arith.div(order.getFreightAmount(), order.getProductNums()) * item.getProdCount();
+                    }
+                    
+                    // 积分抵扣(按商品数量比例分摊)
+                    if (order.getOffsetPoints() != null && order.getProductNums() > 0) {
+                        totalOffsetPoints += Arith.div(Arith.div(Double.valueOf(order.getOffsetPoints()), 100), order.getProductNums()) * item.getProdCount();
+                    }
+                    
+                    // 实付金额(按商品数量比例分摊)
+                    if (order.getActualTotal() != null && order.getProductNums() > 0) {
+                        totalActualAmount += Arith.div(order.getActualTotal(), order.getProductNums()) * item.getProdCount();
+                    }
+                }
+            }
+
+            // 创建总计行(第3行,索引2)
+            Row summaryRow = sheet.createRow(2);
+            summaryRow.setHeightInPoints(20);
+
+            // 序号列显示"总计"
+            ExportUtils.createCell(sheet, summaryRow, 0, 0, 2, "总计", summaryStyle);
+
+            // 其他列填充空白单元格(保持背景色)
+            for (int i = 1; i <= 12; i++) {
+                ExportUtils.createCell(sheet, summaryRow, i, 0, 2, "", summaryStyle);
+            }
+
+            // 商品总数量(索引13)
+            ExportUtils.createCell(sheet, summaryRow, 13, 0, 2, totalProductCount, summaryNumberStyle);
+
+            // 商品总额(索引14)
+            ExportUtils.createCell(sheet, summaryRow, 14, 0, 2, totalAmount, summaryNumberStyle);
+
+            // 运费(索引15)
+            ExportUtils.createCell(sheet, summaryRow, 15, 0, 2, totalFreight, summaryNumberStyle);
+
+            // 积分抵扣(索引16,显示为负数,四舍五入保留后4位)
+            ExportUtils.createCell(sheet, summaryRow, 16, 0, 2, "-" + Arith.round(totalOffsetPoints, 4), summaryNumberStyle);
+
+            // 实付金额(索引17)
+            ExportUtils.createCell(sheet, summaryRow, 17, 0, 2, totalActualAmount, summaryNumberStyle);
+
+            // 后续列填充空白单元格(保持背景色)
+            for (int i = 18; i <= 20; i++) {
+                ExportUtils.createCell(sheet, summaryRow, i, 0, 2, "", summaryStyle);
+            }
         }
 
         /**
@@ -2111,7 +2210,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                 CellStyle dataStyle, CellStyle numberStyle, CellStyle dateStyle,ExportContext context)  throws InterruptedException{
             int batchSize = 100; // 每批处理1000条
             int totalRows = orderList.size();
-            int rowNum = 2; // 从第3行开始(0-based索引)
+            int rowNum = 3; // 从第4行开始(0-based索引),第3行是总计行
             int indexNum = 1; //序号
             for (int i = 0; i < totalRows; i += batchSize) {
                 int end = Math.min(i + batchSize, totalRows);
@@ -2123,13 +2222,16 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
                         break;
 //                    throw new InterruptedException("导出被中断");
                     }
-                    Row row = sheet.createRow(rowNum++);
-                    row.setHeightInPoints(18);
-                    //序号
-                    ExportUtils.createCell(sheet, row, 0, order.getOrderItems().size(), rowNum, indexNum, dataStyle);
-                    fillOrderRowData(sheet, rowNum, row, order, dataStyle, numberStyle, dateStyle);
-                    rowNum += order.getOrderItems().size() - 1;
-                    indexNum++;
+                    // 为每个订单项创建单独的行
+                    for (int itemIndex = 0; itemIndex < order.getOrderItems().size(); itemIndex++) {
+                        Row row = sheet.createRow(rowNum++);
+                        row.setHeightInPoints(18);
+                        OrderItem item = order.getOrderItems().get(itemIndex);
+                        // 序号(每行独立)
+                        ExportUtils.createCell(sheet, row, 0, 0, rowNum, indexNum++, dataStyle);
+                        // 填充订单数据和商品数据
+                        fillOrderRowDataWithItem(sheet, rowNum, row, order, item, dataStyle, numberStyle, dateStyle);
+                    }
                 }
 
                 // 定期刷新到磁盘
@@ -2146,80 +2248,74 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         }
 
         /**
-         * 填充单行订单数据
+         * 填充单行订单数据(包含订单信息和单个商品信息,每行独立不合并)
          */
-        private void fillOrderRowData (Sheet sheet,int rowNum, Row row, Order order,
-                CellStyle dataStyle, CellStyle numberStyle, CellStyle dateStyle){
+        private void fillOrderRowDataWithItem(Sheet sheet, int rowNum, Row row, Order order,
+                OrderItem item, CellStyle dataStyle, CellStyle numberStyle, CellStyle dateStyle) {
 
             // 订单编号
-            ExportUtils.createCell(sheet, row, 1, order.getOrderItems().size(), rowNum, order.getOrderNumber(), dataStyle);
+            ExportUtils.createCell(sheet, row, 1, 0, rowNum, order.getOrderNumber(), dataStyle);
 
             // 下单时间
-            ExportUtils.createCell(sheet, row, 2, order.getOrderItems().size(), rowNum, ExportUtils.formatDate(order.getCreateTime()), dateStyle);
+            ExportUtils.createCell(sheet, row, 2, 0, rowNum, ExportUtils.formatDate(order.getCreateTime()), dateStyle);
 
             // 付款时间
-            ExportUtils.createCell(sheet, row, 3, order.getOrderItems().size(), rowNum, ExportUtils.formatDate(order.getPayTime()), dateStyle);
+            ExportUtils.createCell(sheet, row, 3, 0, rowNum, ExportUtils.formatDate(order.getPayTime()), dateStyle);
 
             // 订单状态
-            ExportUtils.createCell(sheet, row, 4, order.getOrderItems().size(), rowNum, getHbOrderStatus(order.getHbOrderStatus()), dataStyle);
+            ExportUtils.createCell(sheet, row, 4, 0, rowNum, getHbOrderStatus(order.getHbOrderStatus()), dataStyle);
 
             // 订单类型
-            ExportUtils.createCell(sheet, row, 5, order.getOrderItems().size(), rowNum, getDvyType(order.getDvyType()), dataStyle);
-            // 商品明细行(每个订单项一行)
-            fillOrderItems(sheet, rowNum, row, order, dataStyle, numberStyle);
+            ExportUtils.createCell(sheet, row, 5, 0, rowNum, getDvyType(order.getDvyType()), dataStyle);
 
-            // 商品总数量
-            ExportUtils.createCell(sheet, row, 11, order.getOrderItems().size(), rowNum, order.getProductNums(), dataStyle);
+            // 商品名称
+            ExportUtils.createCell(sheet, row, 6, 0, rowNum, item.getProdName(), dataStyle);
 
-            // 商品总额(元)
-            ExportUtils.createCell(sheet, row, 12, order.getOrderItems().size(), rowNum, order.getTotal(), numberStyle);
+            // 海博商品ID
+            ExportUtils.createCell(sheet, row, 7, 0, rowNum, item.getHbSkuId(), dataStyle);
 
-            // 运费(元)
-            ExportUtils.createCell(sheet, row, 13, order.getOrderItems().size(), rowNum, order.getFreightAmount(), numberStyle);
+            // 商品编码
+            ExportUtils.createCell(sheet, row, 8, 0, rowNum, item.getSkuCode(), dataStyle);
 
-            // 积分抵扣(元) - 显示为负数
-            ExportUtils.createCell(sheet, row, 14, order.getOrderItems().size(), rowNum, "-" + (order.getOffsetPoints() == null ? 0 : Arith.div(Double.valueOf(order.getOffsetPoints()), 100)), numberStyle);
+            // 规格
+            ExportUtils.createCell(sheet, row, 9, 0, rowNum, item.getSpec(), dataStyle);
 
-            // 实付金额
-            ExportUtils.createCell(sheet, row, 15, order.getOrderItems().size(), rowNum, order.getActualTotal(), numberStyle);
-
-            // 所属企业
-            ExportUtils.createCell(sheet, row, 16, order.getOrderItems().size(), rowNum, order.getChannelName(), dataStyle);
+            // 单价(元)
+            ExportUtils.createCell(sheet, row, 10, 0, rowNum, item.getPrice(), numberStyle);
 
-            // 买家姓名
-            ExportUtils.createCell(sheet, row, 17, order.getOrderItems().size(), rowNum, order.getReceiver(), dataStyle);
+            // 数量
+            ExportUtils.createCell(sheet, row, 11, 0, rowNum, item.getProdCount(), dataStyle);
 
-            // 买家电话
-            ExportUtils.createCell(sheet, row, 18, order.getOrderItems().size(), rowNum, order.getUserMobile(), dataStyle);
-        }
+            // 小计(元)
+            ExportUtils.createCell(sheet, row, 12, 0, rowNum, item.getProductTotalAmount(), numberStyle);
 
-        /**
-         * 填充订单项明细
-         */
-        private void fillOrderItems (Sheet sheet,int rowNum, Row row, Order order,
-                CellStyle dataStyle, CellStyle numberStyle){
-            int itemSize = order.getOrderItems().size();
+            // 商品总数量(使用当前商品数量)
+            ExportUtils.createCell(sheet, row, 13, 0, rowNum, item.getProdCount(), dataStyle);
 
-            for (int i = 0; i < itemSize; i++) {
-                Row currentRow = (i < 1) ? row : sheet.createRow(rowNum + (i - 1));
-                OrderItem item = order.getOrderItems().get(i);
+            // 商品总额(元) - 每行单独计算,使用当前商品的小计金额
+            ExportUtils.createCell(sheet, row, 14, 0, rowNum, item.getProductTotalAmount(), numberStyle);
 
-                // 商品名称
-                ExportUtils.createCell(sheet, currentRow, 6, 0, rowNum, item.getProdName(), dataStyle);
+            // 运费(元) - 按商品数量比例分摊
+            double freightPerItem = order.getProductNums() > 0 ? Arith.div(order.getFreightAmount(), order.getProductNums()) * item.getProdCount() : 0;
+            ExportUtils.createCell(sheet, row, 15, 0, rowNum, freightPerItem, numberStyle);
 
-                // 规格
-                ExportUtils.createCell(sheet, currentRow, 7, 0, rowNum, item.getSpec(), dataStyle);
+            // 积分抵扣(元) - 按商品数量比例分摊,显示为负数,四舍五入保留后4位
+            double offsetPointsPerItem = (order.getOffsetPoints() != null && order.getProductNums() > 0) 
+                ? Arith.div(Arith.div(Double.valueOf(order.getOffsetPoints()), 100), order.getProductNums()) * item.getProdCount() : 0;
+            ExportUtils.createCell(sheet, row, 16, 0, rowNum, "-" + Arith.round(offsetPointsPerItem, 4), numberStyle);
 
-                // 单价(元)
-                ExportUtils.createCell(sheet, currentRow, 8, 0, rowNum, item.getPrice(), numberStyle);
+            // 实付金额 - 按商品数量比例分摊
+            double actualTotalPerItem = order.getProductNums() > 0 ? Arith.div(order.getActualTotal(), order.getProductNums()) * item.getProdCount() : 0;
+            ExportUtils.createCell(sheet, row, 17, 0, rowNum, actualTotalPerItem, numberStyle);
 
-                // 数量
-                ExportUtils.createCell(sheet, currentRow, 9, 0, rowNum, item.getProdCount(), dataStyle);
+            // 所属企业
+            ExportUtils.createCell(sheet, row, 18, 0, rowNum, order.getChannelName(), dataStyle);
 
-                // 小计(元)
-                ExportUtils.createCell(sheet, currentRow, 10, 0, rowNum, item.getProductTotalAmount(), numberStyle);
+            // 买家姓名
+            ExportUtils.createCell(sheet, row, 19, 0, rowNum, order.getReceiver(), dataStyle);
 
-            }
+            // 买家电话
+            ExportUtils.createCell(sheet, row, 20, 0, rowNum, order.getUserMobile(), dataStyle);
         }
 
         /**

+ 0 - 5
yami-shop-service/src/main/java/com/yami/shop/service/impl/PointsFailureRecordServiceImpl.java

@@ -3,25 +3,20 @@ package com.yami.shop.service.impl;
 
 import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yami.shop.bean.model.PointsFailureRecord;
-import com.yami.shop.bean.vo.ChannelProdExportVO;
 import com.yami.shop.bean.vo.PointsFailureRecordVO;
 import com.yami.shop.bean.vo.RecordExportVO;
 import com.yami.shop.dao.PointsFailureRecordMapper;
 import com.yami.shop.service.PointsFailureRecordService;
 import lombok.AllArgsConstructor;
-import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletResponse;
-import java.lang.reflect.InvocationTargetException;
 import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  * 积分充值失败记录 Service实现类

+ 21 - 12
yami-shop-service/src/main/java/com/yami/shop/service/impl/ShopSkuServiceImpl.java

@@ -1,25 +1,26 @@
 package com.yami.shop.service.impl;
 
 import com.alibaba.excel.EasyExcel;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.yami.shop.bean.model.ChannelProd;
-import com.yami.shop.bean.model.Label;
 import com.yami.shop.bean.model.ShopDetail;
 import com.yami.shop.bean.model.ShopSku;
+import com.yami.shop.bean.po.ProductPageQuery;
 import com.yami.shop.bean.vo.ChannelProdExportVO;
+import com.yami.shop.bean.vo.ProdChannelVO;
+import com.yami.shop.bean.vo.ProductPageVO;
 import com.yami.shop.common.util.PageParam;
 import com.yami.shop.dao.*;
 import com.yami.shop.service.ShopSkuService;
 import lombok.AllArgsConstructor;
-import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletResponse;
 import java.net.URLEncoder;
+import java.util.Date;
 import java.util.List;
+import java.util.Objects;
 
 @Service
 @AllArgsConstructor
@@ -37,21 +38,29 @@ public class ShopSkuServiceImpl extends ServiceImpl<ShopSkuMapper, ShopSku> impl
     }
 
     @Override
-    public IPage<ShopSku> shopSkuPage(PageParam<ShopSku> page,  ShopSku shopSku) {
-        IPage<ShopSku> page1 = shopProdMapper.selectShopSkuPage(page, shopSku);
+    public IPage<ProductPageVO> shopSkuPage(PageParam<ProductPageQuery> page, ProductPageQuery query) {
+        IPage<ProductPageVO> page1 = shopProdMapper.selectShopSkuPage(page, query);
         //循环获取sku和渠道价格设置信息
-        for (ShopSku record : page1.getRecords()) {
-            ShopDetail shopDetail = shopDetailMapper.selectById(record.getShopId());
-            record.setShopName(shopDetail.getShopName());
+        for (ProductPageVO record : page1.getRecords()) {
             record.setSku(skuMapper.selectById(record.getSkuId()));
-            List<ChannelProd> channelProds = channelProdMapper.selectListAll(record.getSkuId(), record.getShopId());
-            record.setChannelProdList(channelProds);
+            List<ProdChannelVO>  channelProds = channelProdMapper.selectListAll(record.getSkuId(), record.getShopId());
+            record.setChannelVOS(channelProds);
+            if (channelProds != null && channelProds.size() > 0){
+                // 获取channelProds最大更新时间
+                Date maxUpdateTime = channelProds.stream()
+                        .map(ProdChannelVO::getUpdateTime)  // 假设ProdChannelVO有getUpdateTime方法
+                        .filter(Objects::nonNull)           // 过滤掉空值
+                        .max(Date::compareTo)               // 找出最大的日期
+                        .orElse(null);                // 如果没有找到,返回null
+
+                record.setUpdateTime(maxUpdateTime);
+            }
         }
         return page1;
     }
 
     @Override
-    public void exportChannelProds(ShopSku shopSku, HttpServletResponse response) {
+    public void exportChannelProds(ProductPageQuery shopSku, HttpServletResponse response) {
         // 查询数据
         List<ChannelProdExportVO> channelProdExportVOS = shopProdMapper.exportList(shopSku);
         try {

+ 38 - 2
yami-shop-service/src/main/java/com/yami/shop/utils/ExportUtils.java

@@ -112,6 +112,13 @@ public class ExportUtils {
      * 创建单元格(字符串类型)
      */
     public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum, String value, CellStyle style) {
+        // 快速路径:不需要合并时直接创建单元格
+        if (size <= 1) {
+            Cell cell = row.createCell(col);
+            cell.setCellValue(value != null ? value : "");
+            cell.setCellStyle(style);
+            return;
+        }
         int lastRow = rowNum + size - 1;
         if (lastRow > rowNum) {
             if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){ //因为索引是从0开始的  所以开始行和结束行都需要减1
@@ -127,9 +134,20 @@ public class ExportUtils {
     }
 
     /**
-     * 创建单元格(数字类型)
+     * 创建单元格(数字类型 - BigDecimal
      */
     public static void createCell(Sheet sheet, Row row, int col, int size, int rowNum, BigDecimal value, CellStyle style) {
+        // 快速路径:不需要合并时直接创建单元格
+        if (size <= 1) {
+            Cell cell = row.createCell(col);
+            if (value != null) {
+                cell.setCellValue(value.doubleValue());
+            } else {
+                cell.setCellValue(0);
+            }
+            cell.setCellStyle(style);
+            return;
+        }
         int lastRow = rowNum + size - 1;
         if (lastRow > rowNum) {
             if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){
@@ -147,9 +165,16 @@ public class ExportUtils {
         cell.setCellStyle(style);
     }
     /**
-     * 创建单元格(数字类型)
+     * 创建单元格(数字类型 - double
      */
     public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum, double value, CellStyle style) {
+        // 快速路径:不需要合并时直接创建单元格
+        if (size <= 1) {
+            Cell cell = row.createCell(col);
+            cell.setCellValue(value);
+            cell.setCellStyle(style);
+            return;
+        }
         int lastRow = rowNum + size - 1;
         if (lastRow > rowNum) {
             if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){
@@ -167,6 +192,17 @@ public class ExportUtils {
      * 创建单元格(整数类型)
      */
     public static void createCell(Sheet sheet,Row row,int col, int size,int rowNum,  Integer value, CellStyle style) {
+        // 快速路径:不需要合并时直接创建单元格
+        if (size <= 1) {
+            Cell cell = row.createCell(col);
+            if (value != null) {
+                cell.setCellValue(value);
+            } else {
+                cell.setCellValue(0);
+            }
+            cell.setCellStyle(style);
+            return;
+        }
         int lastRow = rowNum + size - 1;
         if (lastRow > rowNum) {
             if (!isMergeRegionOverlap(sheet, rowNum-1, lastRow-1, col)){

+ 2 - 2
yami-shop-service/src/main/resources/mapper/ChannelProdMapper.xml

@@ -108,8 +108,8 @@
           AND is_delete = 0
     </select>
 
-    <select id="selectListAll" resultType="com.yami.shop.bean.model.ChannelProd">
-        SELECT c.*, s.shop_name shopName,channel.channel_name channelName,channel.type channelType
+    <select id="selectListAll" resultType="com.yami.shop.bean.vo.ProdChannelVO">
+        SELECT c.id,c.channel_id channelId, c.channel_prod_price price,c.update_time updateTime, channel.channel_name channelName,s.shop_name shopName
         FROM tz_channel_prod c
                  left join tz_shop_detail s on c.shop_id = s.shop_id
                  left join tz_channel channel on c.channel_id = channel.id

+ 12 - 1
yami-shop-service/src/main/resources/mapper/OrderItemMapper.xml

@@ -43,7 +43,7 @@
         </foreach>
     </update>
     <select id="getListByOrderNumber" resultType="com.yami.shop.bean.model.OrderItem">
-        SELECT r.return_money_sts,sku.spec,oi.* FROM tz_order_item oi
+        SELECT r.return_money_sts,sku.spec,sku.hb_sku_id,sku.sku_code,oi.* FROM tz_order_item oi
         JOIN tz_order o ON o.order_number = oi.order_number  AND o.order_number = #{orderNumber}
         LEFT JOIN tz_order_refund r ON r.order_item_id = oi.order_item_id
         LEFT JOIN tz_sku sku on oi.sku_id=sku.sku_id
@@ -94,4 +94,15 @@
         select * from tz_order_item where order_number = #{orderNumber} and sku_id =#{skuId}
     </select>
 
+    <!-- 批量查询订单项(用于导出优化) -->
+    <select id="getListByOrderNumbers" resultType="com.yami.shop.bean.model.OrderItem">
+        SELECT sku.spec, sku.hb_sku_id, sku.sku_code, oi.*
+        FROM tz_order_item oi
+        LEFT JOIN tz_sku sku ON oi.sku_id = sku.sku_id
+        WHERE oi.order_number IN
+        <foreach collection="orderNumbers" item="orderNumber" open="(" close=")" separator=",">
+            #{orderNumber}
+        </foreach>
+    </select>
+
 </mapper>

+ 1 - 1
yami-shop-service/src/main/resources/mapper/OrderMapper.xml

@@ -253,7 +253,7 @@
     </select>
 
     <update id="cancelOrders">
-        update tz_order set `hb_order_status`=60,close_type = 1,cancel_reason = #{cancelReason}, cancel_time =
+        update tz_order set `hb_order_status`=60,cancel_reason = #{cancelReason}, cancel_time =
         NOW(),update_time=NOW(),close_type=4 where order_id in
         <foreach collection="orders" item="order" open="(" close=")" separator=",">
             #{order.orderId}

+ 102 - 35
yami-shop-service/src/main/resources/mapper/ShopSkuMapper.xml

@@ -23,51 +23,118 @@
 
     <select id="selectByShopAndSku" resultType="com.yami.shop.bean.model.ShopSku">
         SELECT s.*, sku.sku_name AS skuName
-        FROM tz_shop_sku s join tz_sku sku on sku.sku_id = s.sku_id and sku.is_delete = 0
+        FROM tz_shop_sku s
+                 join tz_sku sku on sku.sku_id = s.sku_id and sku.is_delete = 0
         WHERE s.shop_id = #{shopId}
           AND s.sku_id = #{skuId}
           AND s.is_delete = 0
     </select>
 
 
-    <select id="selectShopSkuPage" resultMap="shopProdMap">
-        SELECT sk.* FROM tz_shop_sku sk join tz_sku s on sk.sku_id = s.sku_id
-        WHERE s.is_delete = 0 and sk.is_delete = 0
-        <if test="shopSku.shopId != null">
-            AND sk.shop_id = #{shopSku.shopId}
-        </if>
-        <if test="shopSku.skuId != null">
-            AND sk.sku_id = #{shopSku.skuId}
-        </if>
-        <if test="shopSku.skuName != null">
-            AND s.sku_name LIKE CONCAT('%',#{shopSku.skuName},'%')
-        </if>
-        order by sk.rec_time desc
+    <select id="selectShopSkuPage" resultType="com.yami.shop.bean.vo.ProductPageVO">
+        SELECT
+        sku.prod_id spuId,
+        sku.hb_spu_id,
+        sku.pic,
+        sku.sku_name AS skuName,
+        a.prod_name,
+        a.channel_code,
+        sku.hb_sku_id,
+        sku.sku_code,
+        b.shop_id,
+        b.shop_name,
+        c.shop_sku_stocks,
+        sku.sku_id,
+        sku.`status`,
+        MAX(cp.update_time) as update_time
+        from tz_shop_sku c
+        JOIN tz_sku sku ON sku.sku_id = c.sku_id AND sku.is_delete = 0
+        join tz_prod a on a.prod_id = sku.prod_id and a.is_delete = 0
+        JOIN tz_shop_detail b ON c.shop_id = b.shop_id
+        LEFT JOIN tz_channel_prod cp ON c.shop_id = cp.shop_id and sku.sku_id = cp.sku_id and cp.is_delete = 0
+        <where>
+            c.is_delete = 0
+            AND c.id IS NOT NULL
+            AND sku.sku_id IS NOT NULL
+            AND b.shop_id IS NOT NULL
+            <if test='query.keywords!=null and query.keywords.trim() neq ""'>
+                AND ( sku.sku_name LIKE concat('%',#{query.keywords},'%') OR sku.hb_sku_id = #{query.keywords} OR
+                a.hb_spu_id = #{query.keywords})
+            </if>
+            <if test='query.hbSkuId!=null and query.hbSkuId.trim() neq ""'>
+                AND sku.hb_sku_id = #{query.hbSkuId}
+            </if>
+            <if test='query.skuName!=null and query.skuName.trim() neq ""'>
+                AND sku.sku_name LIKE concat('%',#{query.skuName},'%')
+            </if>
+            <if test='query.skuCode!=null and query.skuCode.trim() neq ""'>
+                AND sku.sku_code = #{query.skuCode}
+            </if>
+            <if test='query.shopId!=null'>
+                AND c.shop_id = #{query.shopId}
+            </if>
+            <if test='query.status!=null'>
+                AND a.status = #{query.status} and a.prod_id IS NOT NULL
+            </if>
+            <if test='(query.startTime!=null and query.startTime!="") and (query.endTime!=null and query.endTime!="")'>
+                AND (cp.update_time BETWEEN #{query.startTime} AND #{query.endTime})
+            </if>
+            <if test='(query.minPrice!=null and query.minPrice!="") and (query.maxPrice!=null and query.maxPrice!="")'>
+                AND (cp.channel_prod_price BETWEEN #{query.minPrice} AND #{query.maxPrice})
+            </if>
+        </where>
+        GROUP BY c.shop_id, sku.sku_id, c.shop_sku_stocks,c.rec_time
+        order by c.rec_time desc
     </select>
 
 
     <select id="exportList" resultType="com.yami.shop.bean.vo.ChannelProdExportVO">
         SELECT
-        sha.hb_sku_id AS skuId,
-        sha.sku_name AS skuName,
-        p.channel_id AS channelId,
-        c.channel_name AS channelName,
-        d.shop_name AS shopName,
-        p.purchase_price AS purchasePrice,
-        p.delivery_price AS deliveryPrice,
-        p.channel_prod_price AS channelProdPrice
-        FROM tz_shop_sku sh
-        LEFT JOIN  tz_channel_prod p ON p.shop_id = sh.shop_id and sh.sku_id = p.sku_id and p.is_delete = 0
-        LEFT JOIN tz_channel c ON p.channel_id = c.id
-        LEFT JOIN tz_sku sha ON sh.sku_id = sha.sku_id
-        LEFT JOIN tz_shop_detail d ON sh.shop_id = d.shop_id
-        WHERE sh.is_delete = 0 and sha.is_delete = 0 and p.is_delete = 0
-        <if test="shopSku.shopId != null">
-            AND sh.shop_id = #{shopSku.shopId}
-        </if>
-        <if test="shopSku.skuName != null">
-            AND sha.sku_name LIKE CONCAT('%',#{shopSku.skuName},'%')
-        </if>
-        order by sh.rec_time desc
+        sku.hb_sku_id AS hbSkuId,
+        sku.sku_name AS skuName,
+        b.shop_name AS shopName,
+        c.shop_sku_stocks AS shopSkuStock,
+
+        channel.channel_name channelName,
+        cp.purchase_price purchasePrice,
+        cp.delivery_price deliveryPrice,
+        cp.channel_prod_price channelProdPrice
+
+        from tz_shop_sku c
+        LEFT JOIN tz_sku sku ON sku.sku_id = c.sku_id AND sku.is_delete = 0
+        left join tz_prod a on a.prod_id = sku.prod_id and a.is_delete = 0
+        LEFT JOIN tz_shop_detail b ON c.shop_id = b.shop_id
+        LEFT JOIN tz_channel_prod cp ON c.shop_id = cp.shop_id and sku.sku_id = cp.sku_id and cp.is_delete = 0
+        left join tz_channel channel on cp.channel_id = channel.id
+        <where>
+            c.is_delete = 0
+            AND c.id IS NOT NULL
+            AND sku.sku_id IS NOT NULL
+            AND b.shop_id IS NOT NULL
+            <if test='query.keywords!=null and query.keywords.trim() neq ""'>
+                AND ( sku.sku_name LIKE concat('%',#{query.keywords},'%') OR sku.hb_sku_id = #{query.keywords} OR
+                sku.hb_spu_id = #{query.keywords} )
+            </if>
+
+            <if test='query.hbSkuId!=null and query.hbSkuId.trim() neq ""'>
+                AND sku.hb_sku_id = #{query.hbSkuId}
+            </if>
+            <if test='query.skuCode!=null and query.skuCode.trim() neq ""'>
+                AND sku.sku_code = #{query.skuCode}
+            </if>
+            <if test='query.shopId!=null'>
+                AND c.shop_id = #{query.shopId}
+            </if>
+            <if test='query.status!=null'>
+                AND a.status = #{query.status} and a.prod_id IS NOT NULL
+            </if>
+            <if test='(query.startTime!=null and query.startTime!="") and (query.endTime!=null and query.endTime!="")'>
+                AND (cp.update_time BETWEEN #{query.startTime} AND #{query.endTime})
+            </if>
+            <if test='(query.minPrice!=null and query.minPrice!="") and (query.maxPrice!=null and query.maxPrice!="")'>
+                AND (cp.channel_prod_price BETWEEN #{query.minPrice} AND #{query.maxPrice})
+            </if>
+        </where>
+        order by c.rec_time desc
     </select>
 </mapper>