Răsfoiți Sursa

平台分类

zoujiajian 2 ani în urmă
părinte
comite
b4d26f0da1
26 a modificat fișierele cu 1388 adăugiri și 255 ștergeri
  1. 19 0
      netflix-common/src/main/java/com/cyksj/dto/UserSharedDto.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonCategoryMapper.java
  3. 21 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonCategoryRelateMapper.java
  4. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java
  5. 60 3
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  6. 35 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonCategory.java
  7. 20 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonCategoryRelate.java
  8. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java
  9. 34 2
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java
  10. 40 5
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java
  11. 42 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDetailView.java
  12. 71 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryDetailView.java
  13. 25 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryFrontView.java
  14. 51 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryGoodsView.java
  15. 23 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSearchView.java
  16. 62 10
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java
  17. 133 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListCategoryView.java
  18. 63 27
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListView.java
  19. 19 0
      netflix-dao/src/main/resources/mapper/GoodsDonCategoryRelateMapper.xml
  20. 11 0
      netflix-dao/src/main/resources/mapper/GoodsDonSkuMapper.xml
  21. 30 0
      netflix-service/src/main/java/com/cyksj/service/mange/GoodsDonCategoryService.java
  22. 114 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/GoodsDonCategoryServiceImpl.java
  23. 5 0
      netflix-service/src/main/java/com/cyksj/service/user/UserService.java
  24. 33 0
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  25. 395 201
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  26. 61 7
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

+ 19 - 0
netflix-common/src/main/java/com/cyksj/dto/UserSharedDto.java

@@ -0,0 +1,19 @@
+package com.cyksj.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: UserSharedDto
+ * 创建者: JavaZou
+ * 创建时间:2024/1/2 15:41
+ */
+@Getter
+@Setter
+public class UserSharedDto {
+
+	private Long sharedId;
+
+	private Long dsPopularizeId;
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonCategoryMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDonCategory;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryMapper
+ *创建者: JavaZou
+ *创建时间:2023/8/11 13:40
+ */
+public interface GoodsDonCategoryMapper extends BaseMapper<GoodsDonCategory> {
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonCategoryRelateMapper.java

@@ -0,0 +1,21 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsDonCategory;
+import com.cyksj.model.entity.GoodsDonCategoryRelate;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsDonCategoryRelateMapper
+ * 创建者: JavaZou
+ * 创建时间:2023/10/7 18:14
+ */
+public interface GoodsDonCategoryRelateMapper extends BaseMapper<GoodsDonCategoryRelate> {
+
+	List<GoodsDonCategory> getCateGoryViewByGoodsId(Long goodsId);
+
+	void saveBatchGoodsRelate(@Param("goodsId") Long goodsId, @Param("list") List<Long> categoryList);
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java

@@ -17,4 +17,6 @@ public interface GoodsDonSkuMapper  extends BaseMapper<GoodsDonSku> {
 	List<Long> getSpecificSkuIdsByGoodsIds(@Param("list") List<Long> aiGoodsIds, @Param("months") Integer months);
 
 	List<Long> getSpecificSkuIdsByGoodsId(@Param("goodsId") Long goodsId, @Param("num") Integer num, @Param("months") Integer months);
+
+	GoodsDonSku checkAndReturnMinPriceUserOwnsSku(@Param("goodsId") Long goodsId, @Param("dsUserId") Long dsUserId);
 }

+ 60 - 3
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -17,7 +17,8 @@ import java.util.List;
  */
 @Getter
 @Setter
-@SearchBean(tables = "goods_don")
+@SearchBean(tables = "goods_don g",
+        where = ":condition:")
 public class GoodsDon extends BaseEntity {
 
 
@@ -46,6 +47,12 @@ public class GoodsDon extends BaseEntity {
      */
     private String img;
 
+    /**
+     * 视频封面
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private String videoCover;
+
 
     /**
      * true 上架 / false 下架
@@ -67,13 +74,20 @@ public class GoodsDon extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 1.虚拟,2.实物,3.潮玩,4.租赁
+     */
     private Integer type;
 
     /**
      * 分类
      * 1、AI  2、流媒体
      */
-    private Integer category;
+    private Long category;
+
+    @DbIgnore
+    @TableField(exist = false)
+    private List<Long> categoryList;
 
     /**
      * 二级分类
@@ -83,6 +97,22 @@ public class GoodsDon extends BaseEntity {
 
     private String banner;
 
+    /**
+     * 商品搭配图
+     */
+    private String matchImg;
+
+
+    /**
+     * 是否贴片 false
+     */
+    private Boolean isPatch;
+
+    /**
+     * H5标签
+     */
+    private String mobileTags;
+
     /**
      * 平台分销比例
      */
@@ -138,6 +168,11 @@ public class GoodsDon extends BaseEntity {
      */
     private String payDesc;
 
+    /**
+     * 购买说明
+     */
+    private String buyDesc;
+
     /**
      * 特殊类型
      */
@@ -178,13 +213,35 @@ public class GoodsDon extends BaseEntity {
     @DbIgnore
     private Integer accountCount;
 
+    /**
+     * 是否是特定价格 规格平台
+     */
+    private Boolean isSp;
+
+    /**
+     * 是否有专属用户规格属性
+     */
+    private Boolean isOwns;
+
+    /**
+     * 是否参与分销 默认参与
+     */
+    private Boolean isDistribute;
+
+    /**
+     * 是否开启规格分销 默认未开启
+     */
+    private Boolean isSkuDistribute;
+
     @AllArgsConstructor
     @Getter
     public enum SpecialType {
         recharge("代充"),
+        courseware("课程"),
+        giftCard("礼品卡")
         ;
 
         private String desc;
 
     }
-}
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonCategory.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.cyksj.model.views.GoodsDonCategoryGoodsView;
+import com.ejlchina.searcher.bean.DbIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategory
+ *创建者: JavaZou
+ *创建时间:2023/8/11 13:38
+ */
+@Getter
+@Setter
+public class GoodsDonCategory extends BaseEntity {
+	@NotEmpty(message = "名称不为空")
+	private String name;
+
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String icon;
+
+	private Integer sorted;
+
+	private Boolean status;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private List<GoodsDonCategoryGoodsView> categoryGoodsList;
+}

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonCategoryRelate.java

@@ -0,0 +1,20 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsDonCategoryRelate
+ * 创建者: JavaZou
+ * 创建时间:2023/10/7 18:14
+ */
+@Getter
+@Setter
+public class GoodsDonCategoryRelate extends BaseEntity{
+	private Long goodsId;
+
+	private Long category;
+
+	private Integer sorted;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java

@@ -115,6 +115,12 @@ public class GoodsDonSku extends BaseEntity {
      */
     private BigDecimal hkPrice;
 
+    /**
+     * 专属用户规格
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private String userOwns;
+
     /**
      * 是否开启实物车票时长权益
      */

+ 34 - 2
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java

@@ -33,6 +33,11 @@ public class ReqGoodsSpuInsert {
 
     private String img;
 
+    /**
+     * 视频封面
+     */
+    private String videoCover;
+
     private String tags;
 
     /**
@@ -70,13 +75,34 @@ public class ReqGoodsSpuInsert {
      * 分类
      * 1、AI  2、流媒体
      */
-    private Integer category;
+    private Long category;
+
+    /**
+     * 多分类
+     */
+    private List<Long> categoryList;
 
     /**
      *  轮播图
      */
     private String banner;
 
+    /**
+     * 商品搭配图
+     */
+    private String matchImg;
+
+
+    /**
+     * 是否贴片 false
+     */
+    private Boolean isPatch;
+
+    /**
+     * H5标签
+     */
+    private String mobileTags;
+
     /**
      * 二级分类
      * 虚物品 1邀请制 2非邀请制
@@ -105,6 +131,8 @@ public class ReqGoodsSpuInsert {
      */
     private String payDesc;
 
+    private String buyDesc;
+
     private GoodsDon.SpecialType specialType;
 
 
@@ -122,4 +150,8 @@ public class ReqGoodsSpuInsert {
      * 推荐平台
      */
     private List<Long> recommendGoodsList;
-}
+
+    private Boolean isDistribute;
+
+    private Boolean isSkuDistribute;
+}

+ 40 - 5
netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java

@@ -54,6 +54,12 @@ public class GoodsDonViewer {
     @DbField("img")
     private String img;
 
+    /**
+     * 视频封面
+     */
+    @DbField("g.video_cover")
+    private String videoCover;
+
 
     /**
      * true 上架 / false 下架
@@ -107,11 +113,10 @@ public class GoodsDonViewer {
     private Integer type;
 
     /**
-     * 分类
-     * 1、AI  2、流媒体
+     * 平台分类展示
      */
-    @DbField("g.category")
-    private Integer category;
+    @DbIgnore
+    private List<Long> categoryList;
 
     /**
      * banner
@@ -119,6 +124,24 @@ public class GoodsDonViewer {
     @DbField("g.banner")
     private String banner;
 
+    /**
+     * 商品搭配图
+     */
+    @DbField("g.match_img")
+    private String matchImg;
+
+    /**
+     * 是否贴片 false
+     */
+    @DbField("g.is_patch")
+    private Boolean isPatch;
+
+    /**
+     * H5标签
+     */
+    @DbField("g.mobile_tags")
+    private String mobileTags;
+
     /**
      * 二级分类
      * 虚物品 1邀请制 2非邀请制
@@ -144,6 +167,9 @@ public class GoodsDonViewer {
     @DbField("g.pay_desc")
     private String payDesc;
 
+    @DbField("g.buy_desc")
+    private String buyDesc;
+
     @DbField("g.special_type")
     private GoodsDon.SpecialType specialType;
 
@@ -165,6 +191,15 @@ public class GoodsDonViewer {
     @DbField("g.recommend_goods")
     private String recommendGoods;
 
+    /**
+     * 是否参与分销 默认参与
+     */
+    @DbField("g.is_distribute")
+    private Boolean isDistribute;
+
+    @DbField("g.is_sku_distribute")
+    private Boolean isSkuDistribute;
+
     @DbIgnore
     private List<Long> recommendGoodsList;
-}
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDetailView.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsDonSku;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/5/31 14:15
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g", where = ":condition:")
+public class GoodsDetailView {
+	@DbField("g.id")
+	private Long id;
+
+	/**
+	 * 1.虚拟,2.实物,3.潮玩,4.租赁
+	 */
+	@DbField("g.type")
+	private Integer type;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.status")
+	private Boolean status;
+
+	@DbField("g.deleted")
+	private Boolean deleted;
+
+	@DbIgnore
+	private List<GoodsDonSku> skuList;
+}

+ 71 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryDetailView.java

@@ -0,0 +1,71 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryDetailView
+ *创建者: JavaZou
+ *创建时间:2023/9/1 13:48
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g left join goods_don_category_relate gcr on gcr.goods_id = g.id" +
+		" left join goods_don_category gc on gc.id = gcr.category",
+		where = ":condition:",
+		groupBy = "g.id,g.title,g.status,g.deleted,g.logo,g.type,g.sort_by,g.virtual_sold,g.created_time,g.update_time")
+public class GoodsDonCategoryDetailView {
+	@DbField("g.id")
+	private Long id;
+
+	/**
+	 * 商品名称
+	 */
+	@DbField("g.title")
+	private String title;
+
+	/**
+	 * true 上架 / false 下架
+	 */
+	@DbField("g.status")
+	private Boolean status;
+
+	@DbField("g.deleted")
+	private Boolean deleted;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("g.type")
+	private Integer type;
+
+	/**
+	 * 分类
+	 * 1、AI  2、流媒体
+	 */
+	@DbField("group_concat(gc.name)")
+	private String categoryName;
+
+	/**
+	 * 排序
+	 */
+	@DbField("g.sort_by")
+	private Integer sortBy;
+
+	/**
+	 * 虚拟销量
+	 */
+	@DbField("g.virtual_sold")
+	private Integer virtualSold;
+
+	@DbField("g.created_time")
+	private Date createdTime;
+
+	@DbField("g.update_time")
+	private Date updateTime;
+}

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryFrontView.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryFrontView
+ *创建者: JavaZou
+ *创建时间:2023/8/11 14:13
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don_category gc"
+		, where = "status is true :condition:"
+		, orderBy = "sorted asc")
+public class GoodsDonCategoryFrontView {
+	@DbField("gc.id")
+	private Long id;
+
+	@DbField("gc.name")
+	private String name;
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonCategoryGoodsView.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryGoodsView
+ *创建者: JavaZou
+ *创建时间:2023/8/18 11:11
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g left join goods_don_category_relate gcr on gcr.goods_id = g.id" +
+		" left join goods_don_category gc on gc.id = gcr.category",
+		where = "g.deleted is true and g.status is true")
+public class GoodsDonCategoryGoodsView {
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("gc.name")
+	private String categoryName;
+
+	@DbField("gcr.category")
+	private Long category;
+
+	@DbField("gcr.id")
+	private Long relateId;
+
+	@DbField("g.title")
+	private String title;
+
+	/**
+	 * 前端组件使用
+	 */
+	@DbField("g.title")
+	private String name;
+
+	@DbField("g.status")
+	private Boolean status;
+
+	@DbIgnore
+	private Integer click;
+
+	@DbField("gcr.sorted")
+	private Integer sorted;
+}

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSearchView.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonSearchView
+ *创建者: JavaZou
+ *创建时间:2023/8/25 16:40
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g",
+		where = "g.deleted is true and g.status is true")
+public class GoodsDonSearchView {
+	@DbField("g.id")
+	private Long goodsId;
+
+	private String title;
+}

+ 62 - 10
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java

@@ -1,8 +1,8 @@
 package com.cyksj.model.views;
 
-import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -18,6 +18,7 @@ import java.util.List;
 @Getter
 @Setter
 @SearchBean(tables = "goods_don_sku")
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsDonSkuFrontView {
 
 	private Long id;
@@ -47,6 +48,21 @@ public class GoodsDonSkuFrontView {
 	 */
 	private String notifyText;
 
+	/**
+	 * H5标签
+	 */
+	private String mobileTags;
+
+	/**
+	 * 规格背景图
+	 */
+	private String img;
+
+	/**
+	 * 规格框提示
+	 */
+	private String smallMsg;
+
 	/**
 	 * 商品预览图
 	 */
@@ -74,13 +90,9 @@ public class GoodsDonSkuFrontView {
 	private BigDecimal price;
 
 	/**
-	 * 台币
+	 * 专属用户规格
 	 */
-	private BigDecimal twPrice;
-	/**
-	 * 港币
-	 */
-	private BigDecimal hkPrice;
+	private String userOwns;
 
 	/**
 	 * 月数
@@ -92,8 +104,8 @@ public class GoodsDonSkuFrontView {
 	 */
 	private Integer days;
 
-	@DbField("case when spec_val like '%月%' and spec_val not like '%年%' then 0 when spec_val like '%季%' then 1 when spec_val like '%半年%' then 2 when spec_val like '%年%' then 3 else 66 end")
-	private Integer orderBy;
+//	@DbField("case when spec_val like '%月%' and spec_val not like '%年%' then 0 when spec_val like '%季%' then 1 when spec_val like '%半年%' then 2 when spec_val like '%年%' then 3 else 66 end")
+//	private Integer orderBy;
 
 	private Boolean isDp;
 
@@ -102,4 +114,44 @@ public class GoodsDonSkuFrontView {
 	 */
 	@DbIgnore
 	private List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews;
-}
+
+	/**
+	 * 特定价格
+	 */
+	private BigDecimal specificPrice;
+
+	/**
+	 * 特定购买平台
+	 */
+	private String specificGoodsIds;
+
+	/**
+	 * 排序
+	 */
+	private Integer sorted;
+
+	/**
+	 * 限制次数
+	 */
+	private Integer gptLimitNum;
+
+	/**
+	 * 限制时间
+	 */
+	private Long gptLimitTime;
+
+
+	/**
+	 * mj fast次数
+	 */
+	private Integer mjFastNum;
+
+	/**
+	 * mj relax次数
+	 */
+	private Integer mjRelaxNum;
+
+	private Boolean isCar;
+
+	private Boolean isMirror;
+}

+ 133 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListCategoryView.java

@@ -0,0 +1,133 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsFrontListCategoryView
+ * 创建者: JavaZou
+ * 创建时间:2023/10/12 14:40
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g left join goods_don_category_relate gcr on gcr.goods_id = g.id",
+		where = "g.deleted is true and g.status is true :condition:",
+		orderBy = "gcr.sorted asc, g.id")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class GoodsFrontListCategoryView {
+	@DbField("g.id")
+	private Long id;
+
+	/**
+	 * 商品名称
+	 */
+	@DbField("g.title")
+	private String title;
+
+	/**
+	 * 标签
+	 */
+	@DbField("g.tags")
+	private String tags;
+
+	/**
+	 * 缩略图
+	 */
+	@DbField("g.logo")
+	private String logo;
+
+	/**
+	 * 背景图
+	 */
+	@DbField("g.img")
+	private String img;
+
+	/**
+	 * 分类
+	 * 1、AI  2、流媒体
+	 */
+	@DbField("gcr.category")
+	private Long category;
+
+	/**
+	 * 类型
+	 */
+	@DbField("g.type")
+	private Integer type;
+
+	@DbField("g.second_type")
+	private Integer secondType;
+
+	@DbField("g.special_type")
+	private GoodsDon.SpecialType specialType;
+
+	/**
+	 * 最低规格价格
+	 */
+	@DbField("g.min_price")
+	private BigDecimal price;
+
+	/**
+	 * 最低规格月份
+	 */
+	@DbField("g.min_months")
+	private Integer months;
+
+	/**
+	 * 最低规格天数
+	 */
+	@DbField("g.min_days")
+	private Integer days;
+
+	/**
+	 * 已售
+	 */
+	@DbField("g.virtual_sold")
+	private Integer sold;
+
+	@DbIgnore
+	private BigDecimal specificPrice;
+
+	@DbIgnore
+	private Long specificSkuId;
+
+	@DbField("g.pay_desc")
+	private String payDesc;
+
+	/**
+	 * 是否是特定价格平台
+	 */
+	@DbField("g.is_sp")
+	private Boolean isSp;
+
+
+	@DbField("g.is_owns")
+	private Boolean isOwns;
+
+	@DbField("g.video")
+	private String video;
+
+	/**
+	 * 购买通知信息
+	 */
+	@DbIgnore
+	private String notifyMsg;
+
+	@DbIgnore
+	private List<GoodsDonSkuFrontView> skuList;
+
+	@DbIgnore
+	private GoodsDonSpecFrontView specs;
+
+	@DbIgnore
+	private OrderCommentFrontView comments;
+}

+ 63 - 27
netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListView.java

@@ -1,11 +1,10 @@
 package com.cyksj.model.views;
 
 import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.GoodsDonSpec;
 import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
-import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -21,8 +20,9 @@ import java.util.List;
 @Getter
 @Setter
 @SearchBean(tables = "goods_don g",
-		where = "g.deleted is true and g.status is true and g.type = 1",
-		orderBy = "g.sort_by desc, g.id")
+		where = "g.deleted is true and g.status is true :condition:",
+		orderBy = "g.sort_by asc, g.id")
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsFrontListView {
 	@DbField("g.id")
 	private Long id;
@@ -52,17 +52,45 @@ public class GoodsFrontListView {
 	private String img;
 
 	/**
-	 * 类型
+	 * 视频封面
 	 */
-	@DbField("g.type")
-	private Integer type;
+	@DbField("g.video_cover")
+	private String videoCover;
+
+	@DbField("g.banner")
+	private String banner;
+
+	/**
+	 * 商品搭配图
+	 */
+	@DbField("g.match_img")
+	private String matchImg;
+
+
+	/**
+	 * 是否贴片 false
+	 */
+	@DbField("g.is_patch")
+	private Boolean isPatch;
+
+	/**
+	 * H5标签
+	 */
+	@DbField("g.mobile_tags")
+	private String mobileTags;
 
 	/**
 	 * 分类
 	 * 1、AI  2、流媒体
 	 */
 	@DbField("g.category")
-	private Integer category;
+	private Long category;
+
+	/**
+	 * 类型
+	 */
+	@DbField("g.type")
+	private Integer type;
 
 	@DbField("g.second_type")
 	private Integer secondType;
@@ -76,18 +104,6 @@ public class GoodsFrontListView {
 	@DbField("g.min_price")
 	private BigDecimal price;
 
-	/**
-	 * 台币最低价格
-	 */
-	@DbIgnore
-	private BigDecimal twPrice;
-
-	/**
-	 * 港币最低价格
-	 */
-	@DbIgnore
-	private BigDecimal hkPrice;
-
 	/**
 	 * 最低规格月份
 	 */
@@ -103,15 +119,35 @@ public class GoodsFrontListView {
 	/**
 	 * 已售
 	 */
-	@DbIgnore
+	@DbField("g.virtual_sold")
 	private Integer sold;
 
+	@DbIgnore
+	private BigDecimal specificPrice;
+
+	@DbIgnore
+	private Long specificSkuId;
+
+	@DbField("g.pay_desc")
+	private String payDesc;
+
+	@DbField("g.buy_desc")
+	private String buyDesc;
+
 	/**
-	 * 虚拟销量
+	 * 是否是特定价格平台
 	 */
-	@DbField("g.virtual_sold")
-	@JsonIgnore
-	private Integer virtualSold;
+	@DbField("g.is_sp")
+	private Boolean isSp;
+
+	@DbField("g.is_owns")
+	private Boolean isOwns;
+
+	@DbField("g.detail")
+	private String detail;
+
+	@DbField("g.video")
+	private String video;
 
 	/**
 	 * 购买通知信息
@@ -123,8 +159,8 @@ public class GoodsFrontListView {
 	private List<GoodsDonSkuFrontView> skuList;
 
 	@DbIgnore
-	private GoodsDonSpec specs;
+	private GoodsDonSpecFrontView specs;
 
 	@DbIgnore
 	private OrderCommentFrontView comments;
-}
+}

+ 19 - 0
netflix-dao/src/main/resources/mapper/GoodsDonCategoryRelateMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.GoodsDonCategoryRelateMapper">
+
+    <insert id="saveBatchGoodsRelate">
+        insert
+        ignore into goods_don_category_relate(`goods_id`,`category`,`created_time`,`update_time`)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{goodsId},#{item},now(),now())
+        </foreach>
+    </insert>
+
+
+    <select id="getCateGoryViewByGoodsId" resultType="com.cyksj.model.entity.GoodsDonCategory">
+        select gc.* from goods_don_category gc left join goods_don_category_relate gcr on gcr.category = gc.id
+        where gcr.goods_id = #{goodsId}
+    </select>
+</mapper>

+ 11 - 0
netflix-dao/src/main/resources/mapper/GoodsDonSkuMapper.xml

@@ -25,4 +25,15 @@
           and num = #{num}
           and `months` = #{months}
     </select>
+
+    <select id="checkAndReturnMinPriceUserOwnsSku" resultType="com.cyksj.model.entity.GoodsDonSku">
+        select id,price,months,days
+        from goods_don_sku
+        where goods_id = #{goodsId}
+        and status is true
+        and (user_owns is null
+        <if test="dsUserId != 0">
+            or JSON_CONTAINS(user_owns, '${dsUserId}')
+        </if>) order by price limit 1
+    </select>
 </mapper>

+ 30 - 0
netflix-service/src/main/java/com/cyksj/service/mange/GoodsDonCategoryService.java

@@ -0,0 +1,30 @@
+package com.cyksj.service.mange;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GoodsDonCategory;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryService
+ *创建者: JavaZou
+ *创建时间:2023/8/11 13:45
+ */
+public interface GoodsDonCategoryService extends IService<GoodsDonCategory> {
+	void saveOrUpdateGoods(GoodsDonCategory category);
+
+	void delById(Long id);
+
+	List<GoodsDonCategory> getCateGoryViewByGoodsId(Long id);
+
+	/**
+	 * 批量保存分类关系
+	 */
+	void saveBatchRelate(Long goodsId, List<Long> categoryList);
+
+	/**
+	 * 平台分类关系处理
+	 */
+	void handleGoodsRelate(Long goodsId, List<Long> categoryList);
+}

+ 114 - 0
netflix-service/src/main/java/com/cyksj/service/mange/impl/GoodsDonCategoryServiceImpl.java

@@ -0,0 +1,114 @@
+package com.cyksj.service.mange.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GoodsDonCategoryMapper;
+import com.cyksj.mapper.GoodsDonCategoryRelateMapper;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.GoodsDonCategory;
+import com.cyksj.model.entity.GoodsDonCategoryRelate;
+import com.cyksj.service.mange.GoodsDonCategoryService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsDonCategoryServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/11 13:45
+ */
+@Service
+@RequiredArgsConstructor
+public class GoodsDonCategoryServiceImpl extends ServiceImpl<GoodsDonCategoryMapper, GoodsDonCategory> implements GoodsDonCategoryService {
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final GoodsDonCategoryRelateMapper goodsDonCategoryRelateMapper;
+
+	@Override
+	public void saveOrUpdateGoods(GoodsDonCategory category) {
+		try {
+			this.saveOrUpdate(category);
+		} catch (DuplicateKeyException e) {
+			throw BusinessRuntimeException.getInstance("分类名称重复");
+		}
+	}
+
+	@Override
+	public void delById(Long id) {
+		Integer count = goodsDonMapper.selectCount(Wrappers.lambdaQuery(GoodsDon.class)
+				.eq(GoodsDon::getCategory, id)
+				.eq(GoodsDon::getDeleted, true));
+		if (count > 0) {
+			throw BusinessRuntimeException.getInstance("存在该分类下的商品");
+		}
+		this.removeById(id);
+	}
+
+	@Override
+	public List<GoodsDonCategory> getCateGoryViewByGoodsId(Long goodsId) {
+		List<GoodsDonCategory> categoryList = goodsDonCategoryRelateMapper.getCateGoryViewByGoodsId(goodsId);
+		return categoryList;
+	}
+
+	@Override
+	public void saveBatchRelate(Long goodsId, List<Long> categoryList) {
+		//查询已有的分类
+		categoryList = this.list(Wrappers.lambdaQuery(GoodsDonCategory.class)
+				.in(GoodsDonCategory::getId, categoryList)).stream().map(GoodsDonCategory::getId).collect(Collectors.toList());
+		Long category;
+		if (CollUtil.isNotEmpty(categoryList)) {
+			if (categoryList.size() > 1) {
+				goodsDonCategoryRelateMapper.saveBatchGoodsRelate(goodsId, categoryList);
+				List<Long> sorted = categoryList.stream().sorted(Comparator.comparing((i) -> i)).collect(Collectors.toList());
+				category = sorted.get(0);
+			} else {
+				GoodsDonCategoryRelate goodsDonCategoryRelate = new GoodsDonCategoryRelate();
+				goodsDonCategoryRelate.setGoodsId(goodsId);
+				category = categoryList.get(0);
+				goodsDonCategoryRelate.setCategory(category);
+				goodsDonCategoryRelateMapper.insert(goodsDonCategoryRelate);
+			}
+			goodsDonMapper.update(null, Wrappers.lambdaUpdate(GoodsDon.class)
+					.set(GoodsDon::getCategory, category)
+					.eq(GoodsDon::getId, goodsId));
+		}
+	}
+
+	@Override
+	public void handleGoodsRelate(Long goodsId, List<Long> categoryList) {
+		if (CollUtil.isEmpty(categoryList)) {
+			goodsDonCategoryRelateMapper.delete(Wrappers.lambdaQuery(GoodsDonCategoryRelate.class).eq(GoodsDonCategoryRelate::getGoodsId, goodsId));
+			goodsDonMapper.update(null, Wrappers.lambdaUpdate(GoodsDon.class)
+					.set(GoodsDon::getCategory, 0)
+					.eq(GoodsDon::getId, goodsId));
+			return;
+		}
+		List<GoodsDonCategoryRelate> goodsDonCategoryRelates = goodsDonCategoryRelateMapper.selectList(Wrappers.lambdaQuery(GoodsDonCategoryRelate.class).eq(GoodsDonCategoryRelate::getGoodsId, goodsId));
+		if (goodsDonCategoryRelates.isEmpty()) {
+			saveBatchRelate(goodsId, categoryList);
+			return;
+		}
+		AtomicBoolean ic = new AtomicBoolean(true);
+		//需要删除
+		goodsDonCategoryRelates.forEach(data -> {
+			if (!categoryList.contains(data.getCategory())) {
+				goodsDonCategoryRelateMapper.deleteById(data.getId());
+				categoryList.remove(data.getCategory());
+				ic.set(false);
+			}
+		});
+		if (ic.get() && categoryList.size() == goodsDonCategoryRelates.size()) {
+			return;
+		}
+		saveBatchRelate(goodsId, categoryList);
+	}
+}

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/user/UserService.java

@@ -1,6 +1,7 @@
 package com.cyksj.service.user;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.dto.UserSharedDto;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.request.LoginReq;
@@ -32,4 +33,8 @@ public interface UserService extends IService<User> {
 	 * 验证码登录
 	 */
 	User webLogin(LoginReq loginReq) throws Exception;
+
+	UserSharedDto getUserShredDtoByDsCode(String dsCode);
+
+	Long getSharedIdByUserId(Long userId);
 }

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -15,14 +15,17 @@ import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.dto.UserSharedDto;
 import com.cyksj.mapper.PhoneCodeMapper;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.market.UserBindDetailMapper;
 import com.cyksj.model.dto.OrderDonPostDataDto;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.PhoneCode;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.UserBindDetail;
+import com.cyksj.model.entity.UserDistributeShared;
 import com.cyksj.model.request.LoginReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.user.UserService;
@@ -54,6 +57,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
 	private final PhoneCodeMapper phoneCodeMapper;
 
+	private final UserDistributeSharedMapper userDistributeSharedMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -252,4 +257,32 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		return user;
 	}
 
+	@Override
+	public UserSharedDto getUserShredDtoByDsCode(String dsCode) {
+		Long sharedId = 0l;
+		Long dsPopularizeId = 0l;
+		dsCode = dsCode.trim();
+		User sharedUser = getOne(Wrappers.lambdaQuery(User.class)
+				.eq(User::getShowId, dsCode).last("limit 1"));
+		if (sharedUser != null) {
+			sharedId = sharedUser.getId();
+		}
+		UserSharedDto sharedDto = new UserSharedDto();
+		sharedDto.setSharedId(sharedId);
+		sharedDto.setDsPopularizeId(dsPopularizeId);
+		return sharedDto;
+	}
+
+	@Override
+	public Long getSharedIdByUserId(Long userId) {
+		UserDistributeShared distributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class)
+				.eq(UserDistributeShared::getUserId, userId)
+				.last("limit 1")
+				.select(UserDistributeShared::getSharedId));
+		if (distributeShared == null) {
+			return 0l;
+		}
+		return distributeShared.getSharedId();
+	}
+
 }

+ 395 - 201
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -6,20 +6,23 @@ import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.servlet.ServletUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
-import com.cyksj.common.i18n.I18nMessageUtil;
+import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
-import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
+import com.cyksj.dto.UserSharedDto;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.SysConfigMapper;
-import com.cyksj.model.entity.*;
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.service.user.UserService;
+import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -30,9 +33,14 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -50,12 +58,43 @@ public class GoodsDonController {
 
     private final OrderDonMapper orderDonMapper;
 
-
     private final GoodsDonSkuMapper goodsDonSkuMapper;
 
     private final RedisService redisService;
 
-    private final SysConfigMapper sysConfigMapper;
+    private final UserService userService;
+
+    private final UserBindRelationService userBindRelationService;
+
+    /**
+     * 获取平台商品分类
+     */
+    @GetMapping("/get/category")
+    public Result<List<GoodsDonCategoryFrontView>> getCategory() {
+        String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category";
+        Object o = redisService.get(key);
+        List<GoodsDonCategoryFrontView> list;
+        MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+        String condition = " and (select count(*) from goods_don_category_relate gcr inner join goods_don g on g.id = gcr.goods_id where gcr.category = gc.id) > 0";
+        mapBuilder.put("condition", condition);
+        if (o == null) {
+            list = beanSearcher.searchAll(GoodsDonCategoryFrontView.class, mapBuilder
+                    .build());
+            redisService.setNx(key, list, 30 * 60l);
+            o = redisService.get(key);
+        }
+        list = Jsons.parseList(o, GoodsDonCategoryFrontView.class);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+    }
+
+    /**
+     * 商品搜索
+     */
+    @GetMapping("/search")
+    public Result<SearchResult<GoodsDonSearchView>> search() {
+        SearchResult<GoodsDonSearchView> search = beanSearcher.search(GoodsDonSearchView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 
     /**
      * 获取商品列表
@@ -65,7 +104,7 @@ public class GoodsDonController {
         SearchResult<GoodsDon> search = beanSearcher.search(GoodsDon.class, MapUtils.flatBuilder(request.getParameterMap())
                 .field(GoodsDon::getStatus, true)
                 .field(GoodsDon::getDeleted, true)
-                .orderBy(GoodsDon::getSortBy).desc()
+                .orderBy(GoodsDon::getSortBy).asc()
                 .orderBy(GoodsDon::getId).asc()
                 .build()
         );
@@ -75,171 +114,97 @@ public class GoodsDonController {
                     .orderByAsc(GoodsDonSku::getPrice)
                     .last("limit 1")
                     .select(GoodsDonSku::getPrice));
-            Optional.ofNullable(goodsDonSku).ifPresent(sku->{
+            Optional.ofNullable(goodsDonSku).ifPresent(sku -> {
                 goods.setPrice(goodsDonSku.getPrice());
-                goods.setSoldNum(goods.getVirtualSold() + orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-                        .eq(OrderDon::getGoodsId, goods.getId())
-                        .notIn(OrderDon::getStatus, Constant.noOrderStatus)));
+                goods.setSoldNum(getGoodsSold(goods.getId(), goods.getVirtualSold()));
             });
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
     /**
-     * 推广未登录,虚拟商品列表
+     * 获取商品详情
      */
-    @GetMapping("/get/popularize")
-    public Result<SearchResult<GoodsDonPopularizeView>> getPopularizeVipGoods() {
-        SearchResult<GoodsDonPopularizeView> search = beanSearcher.search(GoodsDonPopularizeView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(GoodsDonPopularizeView::getStatus, true)
-                .field(GoodsDonPopularizeView::getDeleted, true)
-                .field(GoodsDonPopularizeView::getType, 1)
-                .orderBy(GoodsDonPopularizeView::getSortBy).desc()
-                .orderBy(GoodsDonPopularizeView::getId).asc()
-                .build());
-        DateTime now = DateTime.now();
-        search.getDataList().forEach(data -> {
-            data.setSpecs(beanSearcher.searchFirst(GoodsDonSpec.class, MapUtils.builder().field(GoodsDonSpec::getGoodsId, data.getId()).build()));
-            data.setSkuList(beanSearcher.searchAll(GoodsDonSku.class, MapUtils.builder().field(GoodsDonSku::getGoodsId, data.getId()).field(GoodsDonSku::getStatus, true).orderBy(GoodsDonSku::getPrice).asc().build()));
-            Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-                    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-            data.setSold(sold + data.getVirtualSold());
+    @GetMapping("/get/{id}")
+    public Result<? extends Object> getDetail(@PathVariable Long id, String dsCode) {
+        String goodsDetailKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "goods_detail:" + id;
+        //List<Long> filter_goodsIds = getFilterGoodsIds();
+        List<Long> filter_goodsIds = null;
+        //存在过滤平台 商品详情不返回
+        if (CollUtil.isNotEmpty(filter_goodsIds) && filter_goodsIds.contains(id)) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        Object o = redisService.get(goodsDetailKey);
+        if (o == null) {
+            GoodsFrontListView views = beanSearcher.searchFirst(GoodsFrontListView.class, MapUtils.builder().field(GoodsFrontListView::getId, id)
+                    .build());
+            if (views == null) {
+                throw BusinessRuntimeException.getInstance("商品已下架..");
+            }
 
-            Optional.ofNullable(data.getSkuList()).ifPresent(skuList -> {
-                if (skuList.size() > 0) {
-                    GoodsDonSku goodsDonSku = skuList.get(0);
-                    data.setPrice(goodsDonSku.getPrice());
-                    data.setMonths(goodsDonSku.getMonths());
-                }
-            });
-            OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
-                    .eq(OrderDon::getGoodsId, data.getId())
-                    .notIn(OrderDon::getStatus, Constant.noOrderStatus).select(OrderDon::getCreatedTime, OrderDon::getPayTime, OrderDon::getId)
-                    .orderByDesc(OrderDon::getId)
-                    .last("limit 1"));
-            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
-        });
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
-    }
+            views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
+            MapBuilder builder = MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, views.getId()).field(GoodsDonSkuFrontView::getStatus, true);
 
-    /**
-     * 官网首页 平台列表
-     */
-    @GetMapping("/get/list")
-    public Result<List<GoodsFrontListView>> getGoodsList() {
-        List<Long> filter_goodsIds = getFilterGoodsIds(false);
-        String pcCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getNameLanguagePrefix() + "PC";
-        if (CollUtil.isNotEmpty(filter_goodsIds)) {
-            pcCacheKey += ":hz-ip";
-        }
-        Object value = redisService.get(pcCacheKey);
-        if (value != null) {
-            try {
-                List<GoodsFrontListView> list = Jsons.parseList(value, GoodsFrontListView.class);
-                if (CollUtil.isNotEmpty(list)) {
-                    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
-                }
-            } catch (Exception e) {
+            if (views.getType() == 1) {
+                builder.orderBy(GoodsDonSkuFrontView::getSorted).asc();
             }
+            views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, builder.build()));
+            views.setSold(getGoodsSold(views.getId(), views.getSold()));
+            redisService.setNx(goodsDetailKey, views, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 60 * RandomUtil.randomInt(10));
+            o = redisService.get(goodsDetailKey);
         }
-        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
-        if (CollUtil.isNotEmpty(filter_goodsIds)) {
-            builder.field(GoodsFrontListView::getId, filter_goodsIds).op(Operator.NotIn);
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
+        GoodsFrontListView views = Jsons.parseObject(o, GoodsFrontListView.class);
+        AtomicLong dsUserId = new AtomicLong();
+        AtomicBoolean existsChannel = new AtomicBoolean(true);
+        if (StrUtil.isNotBlank(dsCode)) {
+            UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+            dsUserId.set(userSharedDto.getSharedId());
         }
-        List<GoodsFrontListView> list = beanSearcher.searchAll(GoodsFrontListView.class, builder.build());
-        DateTime now = DateTime.now();
-        list.forEach(data -> {
-            data.setSpecs(beanSearcher.searchFirst(GoodsDonSpec.class, MapUtils.builder().field(GoodsDonSpec::getGoodsId, data.getId()).build()));
-            List<GoodsDonSkuFrontView> skuList = beanSearcher.searchAll(GoodsDonSkuFrontView.class, MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, data.getId()).field(GoodsDonSkuFrontView::getStatus, true).orderBy(GoodsDonSkuFrontView::getPrice).asc().build());
-            data.setSkuList(skuList);
-            data.getSkuList().forEach(sku -> {
-                if (sku.getIsDp()) {
-                    List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews = beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelationFrontView.class, MapUtils.builder().field(GoodsDiscountPlusPurchaseRelationFrontView::getSkuId, sku.getId()).build());
-                    sku.setDpSkuViews(dpSkuViews);
+        views.setSkuList(views.getSkuList().stream().filter(sku -> {
+            if (StrUtil.isNotBlank(sku.getUserOwns())) {
+                if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
+                    Long sharedId = userService.getSharedIdByUserId(fUid);
+                    if (sharedId == 0) {
+                        existsChannel.set(false);
+                    }
+                    dsUserId.set(sharedId);
                 }
-            });
-            if (!skuList.isEmpty()) {
-                data.setTwPrice(skuList.get(0).getTwPrice());
-                data.setHkPrice(skuList.get(0).getHkPrice());
-            }
-            Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-                    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-            data.setSold(sold + data.getVirtualSold());
-            OrderCommentFrontView comments = beanSearcher.searchFirst(OrderCommentFrontView.class, MapUtils.builder()
-                    .field(OrderCommentFrontView::getGoodsId, data.getId())
-                    .orderBy(OrderCommentFrontView::getCommentTime).desc()
-                    .orderBy(OrderCommentFrontView::getId).desc()
-                    .build());
-            data.setComments(comments);
-	        data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
-        });
-        redisService.setNx(pcCacheKey, list, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(list);
-    }
-
-    /**
-     * h5 银河首页平台展示
-     */
-    @GetMapping("/get/homePage")
-    public Result<List<GoodsHomePageView>> getGoodsHomePage() {
-        List<Long> filter_goodsIds = getFilterGoodsIds(false);
-        String h5CacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getNameLanguagePrefix() + "H5";
-        if (CollUtil.isNotEmpty(filter_goodsIds)) {
-            h5CacheKey += ":hz-ip";
-        }
-        Object value = redisService.get(h5CacheKey);
-        if (value != null) {
-            try {
-                List<GoodsHomePageView> list = Jsons.parseList(value, GoodsHomePageView.class);
-                if (CollUtil.isNotEmpty(list)) {
-                    return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+                if (dsUserId.get() == 0 || !sku.getUserOwns().contains(String.valueOf(dsUserId.get()))) {
+                    return false;
                 }
-            } catch (Exception e) {
-            }
-        }
-        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
-        if (CollUtil.isNotEmpty(filter_goodsIds)) {
-            builder.field(GoodsFrontListView::getId, filter_goodsIds).op(Operator.NotIn);
-        }
-        List<GoodsHomePageView> dataList = beanSearcher.searchAll(GoodsHomePageView.class, builder.build());
-        DateTime now = DateTime.now();
-        dataList.forEach(data -> {
-            Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-                    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-            data.setSold(sold + data.getVirtualSold());
-            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
-            List<GoodsDonSku> skuList = beanSearcher.searchAll(GoodsDonSku.class, MapUtils.builder().field(GoodsDonSku::getGoodsId, data.getId()).field(GoodsDonSku::getStatus, true).orderBy(GoodsDonSku::getPrice).asc().build());
-            if (!skuList.isEmpty()) {
-                data.setTwPrice(skuList.get(0).getTwPrice());
-                data.setHkPrice(skuList.get(0).getHkPrice());
             }
-        });
-        redisService.setNx(h5CacheKey, dataList, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
-    }
-
-
-    /**
-     * 获取商品详情
-     */
-    @GetMapping("/get/{id}")
-    public Result<GoodsDonViews> getDetail(@PathVariable Long id) {
-        GoodsDonViews views = beanSearcher.searchFirst(GoodsDonViews.class, MapUtils.builder().field(GoodsDonViews::getId, id).build());
-
-        views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
-        MapBuilder builder = MapUtils.builder().field(GoodsDonSku::getGoodsId, views.getId()).field(GoodsDonSku::getStatus, true);
-
-        if (views.getType() == 1) {
-            builder.orderBy(GoodsDonSku::getSorted).asc();
-        }
-        views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, builder.build()));
-        views.getSkuList().forEach(sku -> {
             if (sku.getIsDp()) {
                 sku.setDpSkuViews(beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelationFrontView.class, MapUtils.builder()
                         .field(GoodsDiscountPlusPurchaseRelationFrontView::getSkuId, sku.getId())
                         .build()));
             }
-        });
+            if (views.getIsSp()) {
+                if (fUid == null) {
+                    sku.setSpecificPrice(null);
+                    sku.setSpecificGoodsIds(null);
+                }else {
+                    //设置特定价格
+                    if (!isPaySpecificGoodsIds(sku.getSpecificGoodsIds(), fUid)) {
+                        sku.setSpecificGoodsIds(null);
+                        sku.setSpecificPrice(null);
+                    } else {
+                        BigDecimal specificPrice = views.getSpecificPrice();
+
+                        BigDecimal skuSpecificPrice = sku.getSpecificPrice();
+                        Long specificSkuId = sku.getId();
+                        if (specificPrice == null) {
+                            views.setSpecificPrice(skuSpecificPrice);
+                            views.setSpecificSkuId(specificSkuId);
+                        } else if (specificPrice.compareTo(skuSpecificPrice) > 0) {
+                            views.setSpecificPrice(skuSpecificPrice);
+                            views.setSpecificSkuId(specificSkuId);
+                        }
+                    }
+                }
+            }
+            return true;
+        }).collect(Collectors.toList()));
         return GatewayResponse.SUCCESS.newBuilder().toResult(views);
     }
 
@@ -247,27 +212,60 @@ public class GoodsDonController {
      * 获取商品推荐平台
      */
     @GetMapping("/get/recommend/{id}")
-    public Result<List<GoodsRecommendViews>> getRecommendGoodsByGid(@PathVariable Long id) throws Exception {
-        String key = RedisService.key.YH_HOME_PAGHE_CACHE.getNameLanguagePrefix() + "recommend:" + id;
-        Object value = redisService.get(key);
-        if (value != null) {
-            List<GoodsRecommendViews> goodsRecommendViews = Jsons.parseList(value.toString(), GoodsRecommendViews.class);
-            return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
-        }
-        if (value == null) {
+    public Result<List<GoodsFrontListView>> getRecommendGoodsByGid(@PathVariable Long id, String dsCode) throws Exception {
+        String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "recommend:" + id;
+        Object o = redisService.get(key);
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
+        List<GoodsFrontListView> goodsRecommendViews = null;
+        if (o == null) {
             GoodsDon goodsDon = beanSearcher.searchFirst(GoodsDon.class, MapUtils.builder()
-                    .field(GoodsDon::getId, id)
-                    .field(GoodsDon::getStatus, true)
+                    .field(GoodsDon::getId, id).field(GoodsDon::getStatus, true)
                     .field(GoodsDon::getDeleted, true)
                     .build());
             if (goodsDon != null && StrUtil.isNotEmpty(goodsDon.getRecommendGoods())) {
                 List<Long> recommend_gidList = Jsons.parseList(goodsDon.getRecommendGoods(), Long.class);
-                List<GoodsRecommendViews> goodsRecommendViews = beanSearcher.searchAll(GoodsRecommendViews.class, MapUtils.builder().field(GoodsRecommendViews::getGoodsId, recommend_gidList).op(Operator.InList).build());
+                MapBuilder mapBuilder = MapUtils.builder();
+                mapBuilder.field(GoodsFrontListView::getId, recommend_gidList).op(Operator.InList);
+                goodsRecommendViews = beanSearcher.searchAll(GoodsFrontListView.class, mapBuilder.build());
                 redisService.setNx(key, Jsons.toJson(goodsRecommendViews), 60 * 15l);
-                return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
+                o = redisService.get(key);
+            } else {
+                return GatewayResponse.SUCCESS.newBuilder().toResult();
             }
         }
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
+        if (goodsRecommendViews == null) {
+            goodsRecommendViews = Jsons.parseList(o.toString(), GoodsFrontListView.class);
+        }
+        AtomicLong dsUserId = new AtomicLong();
+        AtomicBoolean existsChannel = new AtomicBoolean(true);
+        if (StrUtil.isNotBlank(dsCode)) {
+            UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+            dsUserId.set(userSharedDto.getSharedId());
+        }
+        goodsRecommendViews = goodsRecommendViews.stream().filter(data -> {
+            if (data.getIsOwns()) {
+                if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
+                    Long sharedId = userService.getSharedIdByUserId(fUid);
+                    if (sharedId == 0) {
+                        existsChannel.set(false);
+                    }
+                    dsUserId.set(sharedId);
+                }
+                GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
+                if (minPriceUserOwnsSku == null) {
+                    return false;
+                }
+                data.setPrice(minPriceUserOwnsSku.getPrice());
+                data.setMonths(minPriceUserOwnsSku.getMonths());
+                data.setDays(minPriceUserOwnsSku.getDays());
+            }
+            //销量
+            data.setSold(getGoodsSold(data.getId(), data.getSold()));
+            //设置特定价格
+            setSpecificPrice(data, fUid, dsUserId.get());
+            return true;
+        }).collect(Collectors.toList());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
     }
 
     /**
@@ -296,30 +294,10 @@ public class GoodsDonController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
-    public List<Long> getFilterGoodsIds(Boolean isOpen) {
-        if (!isOpen) {
-            return null;
-        }
-        //过滤杭州Ai ChatGPT平台
-        //获取当前ip地址
-        SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
-                .eq(SysConfig::getSysKey, Constant.LOCATION_FOR_GOODS_IDS).last("limit 1"));
-        List<Long> filter_goodsIds = null;
-        if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
-            if (StringUtil.getRealAddressByIP(ServletUtil.getClientIP(request)).contains("杭州")) {
-                try {
-                    filter_goodsIds = Jsons.parseList(sysConfig.getSysValue(), Long.class);
-                } catch (Exception e) {
-                }
-            }
-        }
-        return filter_goodsIds;
-    }
 
     /**
-     *
      * @param goodsId
-     * @param type 1、普通,2、注册平台
+     * @param type    1、普通,2、注册平台
      * @return
      */
     public String getPayMsgTime(Long goodsId, DateTime now, Integer type) {
@@ -332,7 +310,7 @@ public class GoodsDonController {
                     .orderByDesc(OrderDon::getId)
                     .last("limit 1"));
             if (orderDon == null) {
-                notifyMsg.append(I18nMessageUtil.getI18nMsg("order_buy_now_notify"));
+                notifyMsg.append("点击购买立即上车");
                 return notifyMsg.toString();
             }
             startTime = orderDon.getPayTime() != null ? orderDon.getPayTime() : orderDon.getCreatedTime();
@@ -341,15 +319,10 @@ public class GoodsDonController {
         if (hour == 0) {
             long minute = DateUtil.between(startTime, now, DateUnit.MINUTE);
             if (minute == 0) {
-                notifyMsg.append("1");
-                notifyMsg.append(I18nMessageUtil.getI18nMsg("minute"));
+                notifyMsg.append("1分钟");
             } else {
                 notifyMsg.append(minute);
-                if (minute > 1) {
-                    notifyMsg.append(I18nMessageUtil.getI18nMsg("minutes"));
-                } else {
-                    notifyMsg.append(I18nMessageUtil.getI18nMsg("minute"));
-                }
+                notifyMsg.append("分钟");
             }
         } else {
             if (hour > 3) {
@@ -358,13 +331,234 @@ public class GoodsDonController {
             } else {
                 notifyMsg.append(hour);
             }
-            if (hour > 1) {
-                notifyMsg.append(I18nMessageUtil.getI18nMsg("hours"));
-            } else {
-                notifyMsg.append(I18nMessageUtil.getI18nMsg("hour"));
-            }
+            notifyMsg.append("小时");
         }
-        notifyMsg.append(I18nMessageUtil.getI18nMsg("order_pre_buy_it"));
+        notifyMsg.append("前有人购买");
         return notifyMsg.toString();
     }
-}
+
+    /**
+     * 是否购买过特定平台
+     */
+    public Boolean isPaySpecificGoodsIds(String specificGoodsIdsStr, Long userId) {
+        if (StrUtil.isNotBlank(specificGoodsIdsStr)) {
+            try {
+                Set<Long> specificGoodsIds = Jsons.parseSet(specificGoodsIdsStr, Long.class);
+                Number number = beanSearcher.searchCount(OrderDon.class, MapUtils.builder().field(OrderDon::getGoodsId, specificGoodsIds).op(Operator.InList)
+                        .field(OrderDon::getUserId, userId)
+                        .field(OrderDon::getStatus, Constant.noOrderAllStatus).op(Operator.NotIn)
+                        .build());
+                if (number.intValue() == 0) {
+                    return false;
+                }
+                return true;
+            } catch (Exception e) {
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 设置平台 特定价格
+     */
+    public void setSpecificPrice(GoodsFrontListView data, Long fUid, Long dsUserId) {
+        if (fUid != null) {
+            if (data.getIsSp()) {
+                //查找所有特定规格最小价格 满足条件
+                String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "specific:" + data.getId();
+                Object speciObj = redisService.get(specificGoodsKey);
+                List<GoodsDonSku> specificSkus = null;
+                if (speciObj != null) {
+                    specificSkus = Jsons.parseList(speciObj, GoodsDonSku.class);
+                } else {
+                    specificSkus = goodsDonSkuMapper.selectList(
+                            Wrappers.lambdaQuery(GoodsDonSku.class)
+                                    .eq(GoodsDonSku::getGoodsId, data.getId())
+                                    .eq(GoodsDonSku::getStatus, true)
+                                    .gt(GoodsDonSku::getSpecificPrice, 0));
+                    redisService.setNx(specificGoodsKey, specificSkus, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+                }
+                specificSkus.forEach(specificSku -> {
+                    if (StrUtil.isNotEmpty(specificSku.getUserOwns()) && (dsUserId == null || !specificSku.getUserOwns().contains(dsUserId.toString()))) {
+                        return;
+                    }
+                    String specificGoodsIdsStr = specificSku.getSpecificGoodsIds();
+                    if (isPaySpecificGoodsIds(specificGoodsIdsStr, fUid)) {
+                        BigDecimal specificPrice = data.getSpecificPrice();
+                        BigDecimal skuSpecificPrice = specificSku.getSpecificPrice();
+                        Long specificSkuId = specificSku.getId();
+                        if (specificPrice == null) {
+                            data.setSpecificPrice(skuSpecificPrice);
+                            data.setSpecificSkuId(specificSkuId);
+                        } else if (specificPrice.compareTo(skuSpecificPrice) > 0) {
+                            data.setSpecificPrice(skuSpecificPrice);
+                            data.setSpecificSkuId(specificSkuId);
+                        }
+                    }
+                });
+                List<GoodsDonSkuFrontView> skuList = data.getSkuList();
+                if (CollUtil.isNotEmpty(skuList)) {
+                    skuList.forEach(sku -> {
+                        //设置特定价格
+                        if (!isPaySpecificGoodsIds(sku.getSpecificGoodsIds(), fUid)) {
+                            sku.setSpecificGoodsIds(null);
+                            sku.setSpecificPrice(null);
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    /**
+     * 设置平台 特定价格
+     */
+    public void setGcSpecificPrice(GoodsFrontListCategoryView data, Long fUid, Long dsUserId) {
+        if (fUid != null) {
+            if (data.getIsSp()) {
+                //查找所有特定规格最小价格 满足条件
+                String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "specific:" + data.getId();
+                Object speciObj = redisService.get(specificGoodsKey);
+                List<GoodsDonSku> specificSkus = null;
+                if (speciObj != null) {
+                    specificSkus = Jsons.parseList(speciObj, GoodsDonSku.class);
+                } else {
+                    specificSkus = goodsDonSkuMapper.selectList(
+                            Wrappers.lambdaQuery(GoodsDonSku.class)
+                                    .eq(GoodsDonSku::getGoodsId, data.getId())
+                                    .eq(GoodsDonSku::getStatus, true)
+                                    .gt(GoodsDonSku::getSpecificPrice, 0));
+                    redisService.setNx(specificGoodsKey, specificSkus, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+                }
+                specificSkus.forEach(specificSku -> {
+                    if (StrUtil.isNotEmpty(specificSku.getUserOwns()) && (dsUserId == null || !specificSku.getUserOwns().contains(dsUserId.toString()))) {
+                        return;
+                    }
+                    String specificGoodsIdsStr = specificSku.getSpecificGoodsIds();
+                    if (isPaySpecificGoodsIds(specificGoodsIdsStr, fUid)) {
+                        BigDecimal specificPrice = data.getSpecificPrice();
+                        BigDecimal skuSpecificPrice = specificSku.getSpecificPrice();
+                        Long specificSkuId = specificSku.getId();
+                        if (specificPrice == null) {
+                            data.setSpecificPrice(skuSpecificPrice);
+                            data.setSpecificSkuId(specificSkuId);
+                        } else if (specificPrice.compareTo(skuSpecificPrice) > 0) {
+                            data.setSpecificPrice(skuSpecificPrice);
+                            data.setSpecificSkuId(specificSkuId);
+                        }
+                    }
+                });
+                List<GoodsDonSkuFrontView> skuList = data.getSkuList();
+                if (CollUtil.isNotEmpty(skuList)) {
+                    skuList.forEach(sku -> {
+                        //设置特定价格
+                        if (!isPaySpecificGoodsIds(sku.getSpecificGoodsIds(), fUid)) {
+                            sku.setSpecificGoodsIds(null);
+                            sku.setSpecificPrice(null);
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    /**
+     * 根据分类获取对应平台
+     */
+    @GetMapping("/get/categoryGoods")
+    public Result<? extends Object> getGoodsByCategory(Long cgy, String dsCode) {
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
+        String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category:goods";
+        if (cgy != null) {
+            categoryGoodsKey += ":" + cgy;
+        }
+        //List<Long> filter_goodsIds = getFilterGoodsIds();
+        List<Long> filter_goodsIds = null;
+        if (CollUtil.isNotEmpty(filter_goodsIds)) {
+            categoryGoodsKey += ":hz-ip";
+        }
+        Object o = redisService.get(categoryGoodsKey);
+        if (o == null) {
+            DateTime now = DateTime.now();
+            MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+            if (cgy != null) {
+                String condition = String.format(" and gcr.category = %s", cgy);
+                mapBuilder.put("condition", condition);
+            }
+            if (CollUtil.isNotEmpty(filter_goodsIds)) {
+                mapBuilder.field(GoodsFrontListCategoryView::getId, filter_goodsIds).op(Operator.NotIn);
+            }
+            List<GoodsFrontListCategoryView> goodsFrontListViews = beanSearcher.searchAll(GoodsFrontListCategoryView.class, mapBuilder.build());
+            goodsFrontListViews.forEach(data -> {
+                data.setSold(getGoodsSold(data.getId(), data.getSold()));;
+                data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
+            });
+            redisService.setNx(categoryGoodsKey, goodsFrontListViews, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 10 * 60);
+            o = redisService.get(categoryGoodsKey);
+        }
+        List<GoodsFrontListCategoryView> goodsFrontListViews = Jsons.parseList(o, GoodsFrontListCategoryView.class);
+        AtomicLong dsUserId = new AtomicLong();
+        AtomicBoolean existsChannel = new AtomicBoolean(true);
+        if (StrUtil.isNotBlank(dsCode)) {
+            UserSharedDto userSharedDto = userService.getUserShredDtoByDsCode(dsCode);
+            dsUserId.set(userSharedDto.getSharedId());
+        }
+        AtomicBoolean filterCourseGoods = new AtomicBoolean(false);
+        //增值服务分类
+        if (fUid != null && cgy != null && (cgy == 3 || cgy == 4)) {
+            //GPT Plus基础2月 课程不展示
+            List<Long> userIdList = userBindRelationService.getRelationUserIdList(fUid, null);
+            Integer orders = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+                    .in(OrderDon::getUserId, userIdList)
+                    .eq(OrderDon::getSkuId, 444)
+                    .notIn(OrderDon::getStatus, Constant.noOrderStatus));
+            if (orders > 0) {
+                filterCourseGoods.set(true);
+            }
+        }
+        goodsFrontListViews = goodsFrontListViews.stream().filter(data -> {
+            if (data.getIsOwns()) {
+                if (dsUserId.get() == 0 && fUid != null && existsChannel.get()) {
+                    Long sharedId = userService.getSharedIdByUserId(fUid);
+                    if (sharedId == 0) {
+                        existsChannel.set(false);
+                    }
+                    dsUserId.set(sharedId);
+                }
+                GoodsDonSku minPriceUserOwnsSku = goodsDonSkuMapper.checkAndReturnMinPriceUserOwnsSku(data.getId(), dsUserId.get());
+                if (minPriceUserOwnsSku == null) {
+                    return false;
+                }
+                data.setPrice(minPriceUserOwnsSku.getPrice());
+                data.setMonths(minPriceUserOwnsSku.getMonths());
+                data.setDays(minPriceUserOwnsSku.getDays());
+            }
+            //课件类型 且过滤
+            if (filterCourseGoods.get() && data.getSpecialType() != null && data.getSpecialType() == GoodsDon.SpecialType.courseware) {
+                return false;
+            }
+            //设置特定价格
+            setGcSpecificPrice(data, fUid, dsUserId.get());
+            return true;
+        }).collect(Collectors.toList());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(goodsFrontListViews);
+    }
+
+    /**
+     * 获取平台销量
+     * @param goodsId
+     * @param virtualSold
+     * @return
+     */
+    private Integer getGoodsSold(Long goodsId, Integer virtualSold) {
+        Object soldObj = redisService.get(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "sold:" + goodsId);
+        if (soldObj == null) {
+            Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+                    .eq(OrderDon::getGoodsId, goodsId).notIn(OrderDon::getStatus, Constant.noOrderStatus));
+            soldObj = sold + virtualSold;
+            redisService.set(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "sold:" + goodsId, soldObj, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+        }
+        return Integer.parseInt(soldObj.toString());
+    }
+
+}

+ 61 - 7
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

@@ -3,17 +3,23 @@ package com.cyksj.web.controller.manage.goods;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.GoodsDonCategory;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.manage.request.ReqGoodsSpuInsert;
 import com.cyksj.model.manage.views.GoodsDonViewer;
+import com.cyksj.model.views.GoodsDetailView;
+import com.cyksj.model.views.GoodsDonCategoryDetailView;
 import com.cyksj.service.mange.CmsGoodsDonService;
+import com.cyksj.service.mange.GoodsDonCategoryService;
 import com.cyksj.service.mange.RefreshCacheService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -29,6 +35,7 @@ import javax.servlet.http.HttpServletRequest;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -49,13 +56,18 @@ public class CmsGoodsDonController {
 
 	private final RefreshCacheService refreshCacheService;
 
-    @GetMapping("/get")
-    public Result<SearchResult<GoodsDon>> get(){
-        SearchResult<GoodsDon> search = beanSearcher.search(GoodsDon.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(GoodsDon::getDeleted,true)
-                .build());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
-    }
+	private final GoodsDonCategoryService goodsDonCategoryService;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	@GetMapping("/get")
+	public Result<SearchResult<GoodsDonCategoryDetailView>> get(){
+		SearchResult<GoodsDonCategoryDetailView> search = beanSearcher.search(GoodsDonCategoryDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(GoodsDonCategoryDetailView::getDeleted,true)
+				.put("condition", "(special_type is null or special_type != 'giftCard')")
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
 
 	/**
 	 * 商品详情
@@ -66,6 +78,8 @@ public class CmsGoodsDonController {
 		if (StrUtil.isNotBlank(goodsDonViewer.getRecommendGoods())) {
 			goodsDonViewer.setRecommendGoodsList(Jsons.parseList(goodsDonViewer.getRecommendGoods(), Long.class));
 		}
+		List<GoodsDonCategory> categoryView = goodsDonCategoryService.getCateGoryViewByGoodsId(id);
+		goodsDonViewer.setCategoryList(categoryView.stream().map(GoodsDonCategory::getId).collect(Collectors.toList()));
 		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonViewer);
 	}
 
@@ -98,6 +112,11 @@ public class CmsGoodsDonController {
 			}
 		}
 		goodsDonService.save(goods);
+		//保存平台 分类的 关联
+		List<Long> categoryList = spu.getCategoryList();
+		if (CollUtil.isNotEmpty(categoryList)) {
+			goodsDonCategoryService.saveBatchRelate(goods.getId(), categoryList);
+		}
 		refreshCacheService.refreshYhHomePageCache();
 		return GatewayResponse.SUCCESS.newBuilder().toResult(goods.getId());
 	}
@@ -136,6 +155,8 @@ public class CmsGoodsDonController {
 			re_goodsIds.remove(spu.getId());
 			goods.setRecommendGoods(Jsons.toJson(re_goodsIds));
 		}
+		//平台 分类关系
+		goodsDonCategoryService.handleGoodsRelate(goods.getId(), spu.getCategoryList());
 		goodsDonService.updateById(goods);
 		refreshCacheService.refreshYhHomePageCache();
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
@@ -189,4 +210,37 @@ public class CmsGoodsDonController {
 				.onlySelect(GoodsDon::getId, GoodsDon::getCategory, GoodsDon::getType, GoodsDon::getTitle, GoodsDon::getSecondType).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDons);
 	}
+
+	/**
+	 * 获取所有平台以及其规格
+	 */
+	@GetMapping("/get/all/goods/sku")
+	public Result<List<GoodsDetailView>> getAllGoodsDetail(Boolean isNoBuyout) {
+		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+		//过滤买断制 平台
+		String conditionSql;
+		if (isNoBuyout != null && isNoBuyout) {
+			mapBuilder.field(GoodsDon::getSpecialType).op(Operator.IsNull);
+			conditionSql = "(select count(*) from goods_don_sku sku where sku.goods_id = g.id and sku.months = 300) = 0";
+		} else {
+			conditionSql = "(special_type is null or special_type != 'giftCard')";
+		}
+		conditionSql += "  and exists (select id from goods_don_sku sku where sku.goods_id = g.id limit 1)";
+
+		List<GoodsDetailView> goodsDons = beanSearcher.searchAll(GoodsDetailView.class, mapBuilder
+				.put("condition", conditionSql)
+				.field(GoodsDetailView::getType, 1)
+				.field(GoodsDetailView::getStatus, 1)
+				.field(GoodsDetailView::getDeleted, true)
+				.onlySelect(GoodsDetailView::getId, GoodsDetailView::getTitle)
+				.build());
+		goodsDons.forEach(e->{
+			List<GoodsDonSku> donSkus = skuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
+					.eq(GoodsDonSku::getGoodsId, e.getId())
+					.eq(GoodsDonSku::getStatus, 1).select(GoodsDonSku::getId, GoodsDonSku::getSpecVal));
+			e.setSkuList(donSkus);
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDons);
+	}
+
 }