Răsfoiți Sursa

Merge branch 'sp_email_func'

# Conflicts:
#	netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java
zoujiajian 3 ani în urmă
părinte
comite
e85c4a5348
26 a modificat fișierele cu 510 adăugiri și 125 ștergeri
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsCoursewareFileMapper.java
  2. 29 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsCoursewareFile.java
  3. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  4. 10 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDonSku.java
  5. 10 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java
  6. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  7. 23 0
      netflix-dao/src/main/java/com/cyksj/model/request/SpecialGoodsTicketReq.java
  8. 12 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java
  9. 2 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java
  10. 17 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListView.java
  11. 0 104
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsHomePageView.java
  12. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsRecommendViews.java
  13. 1 1
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  14. 5 0
      netflix-service/src/main/java/com/cyksj/service/mail/MailService.java
  15. 84 0
      netflix-service/src/main/java/com/cyksj/service/mail/impl/MailServiceImpl.java
  16. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonServiceImpl.java
  17. 15 0
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSpecServiceImpl.java
  18. 31 1
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  19. 6 1
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  20. 48 3
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  21. 110 14
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  22. 34 0
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  23. 3 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java
  24. 19 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java
  25. 3 1
      netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java
  26. 7 0
      netflix-web/src/main/java/com/cyksj/web/util/StpUserUtil.java

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

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

+ 29 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsCoursewareFile.java

@@ -0,0 +1,29 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: goods_courseware_file
+ *创建者: JavaZou
+ *创建时间:2023/8/24 10:51
+ */
+@Getter
+@Setter
+public class GoodsCoursewareFile extends BaseEntity{
+	private Long goodsId;
+
+	/**
+	 * 邮箱标题
+	 */
+	private String subject;
+
+	private String fileName;
+
+	private String path;
+
+	private String img;
+
+	private Boolean status;
+}

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

@@ -178,10 +178,16 @@ public class GoodsDon extends BaseEntity {
     @DbIgnore
     private Integer accountCount;
 
+    /**
+     * 是否是特定价格 规格平台
+     */
+    private Boolean isSp;
+
     @AllArgsConstructor
     @Getter
     public enum SpecialType {
         recharge("代充"),
+        courseware("课件")
         ;
 
         private String desc;

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

@@ -124,6 +124,16 @@ public class GoodsDonSku extends BaseEntity {
      */
     private Boolean isDp;
 
+    /**
+     * 特定价格
+     */
+    private BigDecimal specificPrice;
+
+    /**
+     * 特定平台购买用户人群
+     */
+    private String specificGoodsIds;
+
     /**
      * 优惠加购商品规格展示
      */

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuInsert.java

@@ -91,6 +91,16 @@ public class ReqGoodsSkuInsert {
          */
         private List<GoodsDiscountPlusPurchaseRelation> dpSku;
 
+        /**
+         * 特定价格
+         */
+        private String specificPrice;
+
+        /**
+         * 特定平台购买用户人群
+         */
+        private String specificGoodsIds;
+
     }
 
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -104,4 +104,9 @@ public class OrderPayRequest {
     private String callback;
 
     private String callbackType;
+
+    /**
+     * 是否是特定价格
+     */
+    private Boolean isSpecificPrice;
 }

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/request/SpecialGoodsTicketReq.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+
+/*
+ *项目名: netflix
+ *文件名: CoursewareReq
+ *创建者: JavaZou
+ *创建时间:2023/8/23 17:32
+ */
+@Getter
+@Setter
+public class SpecialGoodsTicketReq {
+	@NotNull
+	private Long relationId;
+
+	private String email;
+
+	private Long userId;
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java

@@ -3,6 +3,7 @@ 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.JsonIgnore;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -93,4 +94,15 @@ public class GoodsDonSkuFrontView {
 	 */
 	@DbIgnore
 	private List<GoodsDiscountPlusPurchaseRelationFrontView> dpSkuViews;
+
+	/**
+	 * 特定价格
+	 */
+	private BigDecimal specificPrice;
+
+	/**
+	 * 特定购买平台
+	 */
+	@JsonIgnore
+	private String specificGoodsIds;
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java

@@ -122,6 +122,8 @@ public class GoodsDonViews {
      */
     private String recommendGoods;
 
+    private Boolean isSp;
+
     @DbIgnore
     private List<GoodsDonSkuFrontView> skuList;
 

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsFrontListView.java

@@ -6,6 +6,7 @@ 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;
 
@@ -23,6 +24,7 @@ import java.util.List;
 @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")
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsFrontListView {
 	@DbField("g.id")
 	private Long id;
@@ -101,6 +103,21 @@ public class GoodsFrontListView {
 	@JsonIgnore
 	private Integer virtualSold;
 
+	@DbIgnore
+	private BigDecimal specificPrice;
+
+	@DbIgnore
+	private Long specificSkuId;
+
+	@DbField("g.pay_desc")
+	private String payDesc;
+
+	/**
+	 * 是否是特定价格平台
+	 */
+	@DbField("g.is_sp")
+	private Boolean isSp;
+
 	/**
 	 * 购买通知信息
 	 */

+ 0 - 104
netflix-dao/src/main/java/com/cyksj/model/views/GoodsHomePageView.java

@@ -1,104 +0,0 @@
-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.JsonIgnore;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.math.BigDecimal;
-
-/*
- *项目名: netflix
- *文件名: GoodsHomePageView
- *创建者: JavaZou
- *创建时间:2023/4/14 11:12
- */
-@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")
-public class GoodsHomePageView {
-	@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;
-
-	/**
-	 * 类型
-	 */
-	@DbField("g.type")
-	private Integer type;
-
-	/**
-	 * 分类
-	 * 1、AI  2、流媒体
-	 */
-	@DbField("g.category")
-	private Integer category;
-
-	/**
-	 * 最低规格价格
-	 */
-	@DbField("g.min_price")
-	private BigDecimal price;
-
-	/**
-	 * 最低规格月份
-	 */
-	@DbField("g.min_months")
-	private Integer months;
-
-	/**
-	 * 最低规格天数
-	 */
-	@DbField("g.min_days")
-	private Integer days;
-
-	/**
-	 * 已售
-	 */
-	@DbIgnore
-	private Integer sold;
-
-	/**
-	 * 虚拟销量
-	 */
-	@DbField("g.virtual_sold")
-	@JsonIgnore
-	private Integer virtualSold;
-
-	@DbField("g.special_type")
-	private GoodsDon.SpecialType specialType;
-
-	@DbField("g.pay_desc")
-	private String payDesc;
-
-	/**
-	 * 购买通知信息
-	 */
-	@DbIgnore
-	private String notifyMsg;
-}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsRecommendViews.java

@@ -51,6 +51,12 @@ public class GoodsRecommendViews {
 	@DbField("g.virtual_sold")
 	private Integer virtualSold;
 
+	@DbField("g.specific_price")
+	private BigDecimal specificPrice;
+
+	@DbField("g.specific_goods_ids")
+	private String specificGoodsIds;
+
 	@DbIgnore
 	private Integer sold;
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -611,7 +611,7 @@ public class RedisService {
         BUSINESS_FIRST_ORDER_USER_KEY("business_first_order_user_key:%s:", "商务分销首单提成key", 60l),
         PC_WEB_CACHE("pc_web_cache", "首页平台缓存", 10 * 60),
         H5_WEB_CACHE("h5_web_cache", "h5首页平台缓存", 10 * 60),
-        YH_HOME_PAGHE_CACHE("yh_home_paghe_cache:", "银河首页缓存", 10 * 60),
+        YH_HOME_PAGHE_CACHE("yh_home_paghe_cache:", "银河首页缓存", 30 * 60),
         REGISTER_HOME_PAGE_CACHE("register_home_page_cache:", "注册首页缓存", 10 * 60),
         CPS_BACK_LOGIN_KEY("cps_back_login:", "cps商务后台登录key", 3 * 60),
         CPS_AUTH_SUCCESS_KEY("cps_auth_success_key:%s", "cps后台微信授权", 60 * 10),

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/mail/MailService.java

@@ -16,4 +16,9 @@ public interface MailService {
 	Boolean sendLoginCodeEmailToPeople(String code, String toAddress);
 
 	void sendEmailMsgToPeople(String people, String subject, String msg);
+
+	/**
+	 * 发送课程给用户
+	 */
+	void sendCoursewareByGoodsId(Long goodsId, Long relationId, Long userId, String goodsTitle, String email) throws Exception;
 }

+ 84 - 0
netflix-service/src/main/java/com/cyksj/service/mail/impl/MailServiceImpl.java

@@ -1,6 +1,16 @@
 package com.cyksj.service.mail.impl;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.GoodsCoursewareFileMapper;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.model.entity.GoodsCoursewareFile;
+import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.entity.OrderDon;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.mail.MailService;
 import lombok.RequiredArgsConstructor;
@@ -9,8 +19,14 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.mail.MailException;
 import org.springframework.mail.SimpleMailMessage;
 import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
 import org.springframework.stereotype.Service;
 
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeUtility;
+import java.io.File;
+import java.util.List;
+
 /*
  *项目名: netflix
  *文件名: MailServiceImpl
@@ -28,6 +44,16 @@ public class MailServiceImpl implements MailService {
 
 	private final RedisService redisService;
 
+	private final GoodsCoursewareFileMapper coursewareFileMapper;
+
+	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private static String IMG_HTML = "<p><img src='%s' width=200></p>";
+
 	@Override
 	public String sendLoginCodeEmailToPeople(Integer digit, String toAddress) {
 		// 生成验证码
@@ -60,6 +86,64 @@ public class MailServiceImpl implements MailService {
 		}
 	}
 
+	@Override
+	public void sendCoursewareByGoodsId(Long goodsId, Long relationId, Long userId, String goodsTitle, String email) throws Exception {
+		//获取当前目前下的课程文件
+		MimeMessage msg = mailSender.createMimeMessage();
+		MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8");
+		List<GoodsCoursewareFile> coursewareFiles = coursewareFileMapper.selectList(Wrappers.lambdaQuery(GoodsCoursewareFile.class)
+				.eq(GoodsCoursewareFile::getGoodsId, goodsId)
+				.eq(GoodsCoursewareFile::getStatus, true));
+		if (coursewareFiles.isEmpty()) {
+			throw BusinessRuntimeException.getInstance("未配置对应课件,请联系客服..");
+		}
+		//标题
+		StringBuilder subject = new StringBuilder();
+		StringBuilder sb = new StringBuilder(IMG_HTML.length());
+		coursewareFiles.forEach(file->{
+			try {
+				helper.addAttachment(MimeUtility.encodeText(file.getFileName(), "utf-8", "B"), new File(file.getPath()));
+				if (StrUtil.isNotBlank(file.getImg())) {
+					sb.append(String.format(IMG_HTML, file.getImg()));
+					sb.append("<br/>");
+				}
+				if (subject.length() > 0) {
+					subject.append(StrUtil.EMPTY);
+				}
+				subject.append(file.getSubject());
+			} catch (Exception e) {
+			}
+		});
+		if (sb.length() == 0) {
+			sb.append(goodsTitle);
+		}
+		if (subject.length() == 0) {
+			subject.append("银河录像局AI课程");
+		}
+		helper.setSubject(subject.toString());
+		helper.setText(sb.toString(), true);
+		helper.setFrom(from);
+		helper.setTo(email);
+		TASK_EXECUTOR.execute(() -> {
+			try {
+				log.info("开始给用户userId:{},relationId:{} 发送课程:{}专属课件", userId, relationId, goodsTitle);
+				mailSender.send(msg);
+			} catch (Exception e) {
+				log.info("发送课件失败,error:{}", StringUtil.getErrorText(e));
+				groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+						.set(GroupsRelation::getAccount, null)
+						.eq(GroupsRelation::getId, relationId)
+						.and(qr -> qr.isNotNull(GroupsRelation::getAccount).or().ne(GroupsRelation::getAccount, StrUtil.EMPTY)));
+
+				orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class)
+						.set(OrderDon::getStatus, OrderDon.Status.hasPayment)
+						.eq(OrderDon::getRelationId, relationId)
+						.eq(OrderDon::getUserId, userId)
+						.eq(OrderDon::getStatus, OrderDon.Status.complete));
+			}
+		});
+	}
+
 
 	public boolean sendMail(String toAddress, String subject, String text) {
 		SimpleMailMessage msg = new SimpleMailMessage();

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.mange.goods;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.mapper.GoodsDonMapper;
@@ -11,6 +12,7 @@ import com.ejlchina.searcher.BeanSearcher;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Optional;
 
@@ -34,7 +36,16 @@ public class CmsGoodsDonServiceImpl extends ServiceImpl<GoodsDonMapper, GoodsDon
 				.eq(GoodsDonSku::getGoodsId, goodsId)
 				.eq(GoodsDonSku::getStatus, true)
 				.orderByAsc(GoodsDonSku::getPrice));
+		//是否有特定价格规格
+		if (goods.getIsSp() && CollUtil.isEmpty(skuViews)) {
+			goods.setIsSp(false);
+			goodsDonMapper.updateById(goods);
+		}
 		if (!skuViews.isEmpty()) {
+			//是否有特定价格规格
+			Optional<GoodsDonSku> specificSkuAny = skuViews.stream().filter(sku -> sku.getSpecificPrice().compareTo(BigDecimal.ZERO) > 0).findAny();
+			goods.setIsSp(specificSkuAny.isPresent() ? true : false);
+
 			GoodsDonSku min = skuViews.get(0);
 			goods.setMinPrice(min.getPrice());
 			if (min.getDays() == null) {

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSpecServiceImpl.java

@@ -238,6 +238,21 @@ public class CmsGoodsDonSpecServiceImpl extends ServiceImpl<GoodsDonSpecMapper,
 				if (sku.getMonths() == null && sku.getDays() == null)
 					throw BusinessRuntimeException.getInstance("请输入对应续费时间");
 			}
+			String specificGoodsIds = goodsDonSku.getSpecificGoodsIds();
+			if (StrUtil.isNotBlank(specificGoodsIds)) {
+				Set<Long> specificGids = Jsons.parseSet(specificGoodsIds, Long.class);
+				Integer count = goodsDonMapper.selectCount(Wrappers.lambdaQuery(GoodsDon.class)
+						.in(GoodsDon::getId, specificGids)
+						.eq(GoodsDon::getStatus, true)
+						.eq(GoodsDon::getDeleted, true));
+				if (count != specificGids.size()) {
+					throw BusinessRuntimeException.getInstance("存在被删除或已下架的平台");
+				}
+				BigDecimal specificPrice = goodsDonSku.getSpecificPrice();
+				if (specificPrice == null || specificPrice.compareTo(BigDecimal.ZERO) <= 0) {
+					throw BusinessRuntimeException.getInstance("请输入正确的特定价格");
+				}
+			}
 			goodsDonSkuMapper.insert(goodsDonSku);
 
 		}

+ 31 - 1
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -260,7 +260,33 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
 			throw BusinessRuntimeException.getInstance("下单商品价格异常");
 		}
-		if (payRequest.getDonMoney().compareTo(sku.getPrice()) < 0) {
+		//是否是特定价格 且是否满足
+		Boolean isSpecificPrice = Optional.ofNullable(payRequest.getIsSpecificPrice()).orElse(false);
+		String specificGoodsIds = sku.getSpecificGoodsIds();
+		BigDecimal specificPrice = BigDecimal.ZERO;
+		if (isSpecificPrice) {
+			if (StrUtil.isEmpty(specificGoodsIds)) {
+				throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重试");
+			}
+			if (payRequest.getDonMoney().compareTo(sku.getSpecificPrice()) <= 0) {
+				payRequest.setDonMoney(sku.getSpecificPrice());
+			}
+			List<Long> specificGoodsList = Jsons.parseList(specificGoodsIds, Long.class);
+			if (CollUtil.isEmpty(specificGoodsList)) {
+				throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重试");
+			}
+			if (user.getId() == 0) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+			Number count = beanSearcher.searchCount(OrderDon.class, MapUtils.builder().field(OrderDon::getGoodsId, specificGoodsList).op(Operator.InList)
+					.field(OrderDon::getUserId, user.getId())
+					.field(OrderDon::getStatus, Constant.noOrderAllStatus).op(Operator.NotIn)
+					.build());
+			if (count.intValue() <= 0) {
+				throw BusinessRuntimeException.getInstance("你不满足该商品特定价格条件");
+			}
+			specificPrice = sku.getSpecificPrice();
+		}
+
+		if (payRequest.getDonMoney().compareTo(sku.getPrice()) < 0 && !isSpecificPrice) {
 			log.info("规格:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", sku.getSpecVal(), payRequest.getDonMoney(), user.getId(), sku.getPrice());
 			payRequest.setDonMoney(sku.getPrice());
 		}
@@ -301,6 +327,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//扣除使用优惠券、余额的订单金额
 		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
 
+		if (isSpecificPrice && (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0 || orderDon.getMoney().compareTo(specificPrice) != 0)) {
+			throw BusinessRuntimeException.getInstance("专属价格不支持使用其他优惠");
+		}
+
 		orderDon.setSkuId(payRequest.getSkuId());
 		orderDon.setRelationId(relationId);
 		orderDon.setNum(payRequest.getNum());

+ 6 - 1
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -1,8 +1,8 @@
 package com.cyksj.service.relation;
 
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.request.SpecialGoodsTicketReq;
 import com.cyksj.model.views.RenewalView;
 import com.cyksj.model.views.UserRecommendGoodsFrontView;
 
@@ -22,4 +22,9 @@ public interface GroupRelationFrontService {
 	GroupsRelation getSimilarExpiredGroupRelation(Long skuId, Integer days, Integer months, List<Long> errorsRelationIds);
 
 	Page<UserRecommendGoodsFrontView> getRecommendGoodsViews(Boolean isPayNf, List<Long> filter_goods_id, Integer start, Integer limit);
+
+	/**
+	 * 通过邮件发送课程
+	 */
+	void sendCourseWare(SpecialGoodsTicketReq request) throws Exception;
 }

+ 48 - 3
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -3,19 +3,22 @@ package com.cyksj.service.relation.impl;
 import cn.hutool.core.date.BetweenFormater;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.UserMapper;
-import com.cyksj.model.entity.CouponUser;
-import com.cyksj.model.entity.GroupsRelation;
-import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.SpecialGoodsTicketReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.ChatGptAuthService;
+import com.cyksj.service.mail.MailService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.user.UserBindRelationService;
@@ -25,6 +28,7 @@ import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -54,6 +58,10 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final RedisService redisService;
 
+	private final MailService mailService;
+
+	private final OrderDonMapper orderDonMapper;
+
 	@Override
 	public List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize) {
 		User u = userMapper.selectById(userId);
@@ -186,4 +194,41 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	public Page<UserRecommendGoodsFrontView> getRecommendGoodsViews(Boolean isPayNf, List<Long> filter_goods_id, Integer start, Integer limit) {
 		return groupsRelationMapper.getRecommendGoodsViews(new Page<>(start, limit),filter_goods_id, isPayNf);
 	}
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void sendCourseWare(SpecialGoodsTicketReq request) throws Exception {
+		Long userId = request.getUserId();
+		Long relationId = request.getRelationId();
+		String email = request.getEmail();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		RenewalView relation = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getRelationId, relationId).build());
+		Assert.notNull(relation, "您的车票不存在");
+		Long relationUserId = relation.getUserId();
+		if (!userIdList.contains(relationUserId)) {
+			throw BusinessRuntimeException.getInstance("您的车票不存在");
+		}
+		if (relation.getSpecialType() != GoodsDon.SpecialType.courseware) {
+			throw BusinessRuntimeException.getInstance("");
+		}
+		//是否已发送
+		if (StrUtil.isNotBlank(relation.getGrAccount())) {
+			throw BusinessRuntimeException.getInstance("已领取课件,请前往邮箱查看");
+		}
+		if (!Validator.isEmail(email)) {
+			throw BusinessRuntimeException.getInstance("请输入正确的邮箱");
+		}
+		int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+				.set(GroupsRelation::getAccount, email)
+				.and(qr -> qr.isNull(GroupsRelation::getAccount).or().eq(GroupsRelation::getAccount, StrUtil.EMPTY))
+				.eq(GroupsRelation::getId, relationId));
+		if (update > 0) {
+			orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class)
+					.set(OrderDon::getStatus, OrderDon.Status.complete)
+					.eq(OrderDon::getRelationId, relationId)
+					.eq(OrderDon::getUserId, userId)
+					.eq(OrderDon::getStatus, OrderDon.Status.hasPayment));
+			mailService.sendCoursewareByGoodsId(relation.getGoodsId(), relation.getRelationId(), relation.getUserId(), relation.getTitle(), email);
+		}
+	}
 }

+ 110 - 14
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -15,11 +15,12 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.SysConfigMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.mapper.SysConfigMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -30,9 +31,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
+import java.math.BigDecimal;
+import java.util.*;
 
 /**
  * @author chan
@@ -90,6 +90,7 @@ public class GoodsDonController {
      * 推广未登录,虚拟商品列表
      */
     @GetMapping("/get/popularize")
+    @Deprecated
     public Result<SearchResult<GoodsDonPopularizeView>> getPopularizeVipGoods() {
         SearchResult<GoodsDonPopularizeView> search = beanSearcher.search(GoodsDonPopularizeView.class, MapUtils.flatBuilder(request.getParameterMap())
                 .field(GoodsDonPopularizeView::getStatus, true)
@@ -161,11 +162,14 @@ public class GoodsDonController {
         if (CollUtil.isNotEmpty(filter_goodsIds)) {
             pcCacheKey += ":hz-ip";
         }
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
         Object value = redisService.get(pcCacheKey);
         if (value != null) {
             try {
-                List<GoodsFrontListView> list = Jsons.parseObject(value, List.class);
+                List<GoodsFrontListView> list = Jsons.parseList(value, GoodsFrontListView.class);
                 if (CollUtil.isNotEmpty(list)) {
+                    //设置特定价格
+                    setSpecificPrice(list, fUid);
                     return GatewayResponse.SUCCESS.newBuilder().toResult(list);
                 }
             } catch (Exception e) {
@@ -195,9 +199,11 @@ public class GoodsDonController {
                     .orderBy(OrderCommentFrontView::getId).desc()
                     .build());
             data.setComments(comments);
-	        data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
+            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
         });
         redisService.setNx(pcCacheKey, list, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+        //设置特定价格
+        setSpecificPrice(list, fUid);
         return GatewayResponse.SUCCESS.newBuilder().toResult(list);
     }
 
@@ -205,17 +211,20 @@ public class GoodsDonController {
      * h5 银河首页平台展示
      */
     @GetMapping("/get/homePage")
-    public Result<List<GoodsHomePageView>> getGoodsHomePage() {
+    public Result<List<GoodsFrontListView>> getGoodsHomePage() {
         List<Long> filter_goodsIds = getFilterGoodsIds();
         String h5CacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "H5";
         if (CollUtil.isNotEmpty(filter_goodsIds)) {
             h5CacheKey += ":hz-ip";
         }
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
         Object value = redisService.get(h5CacheKey);
         if (value != null) {
             try {
-                List<GoodsHomePageView> list = Jsons.parseObject(value, List.class);
+                List<GoodsFrontListView> list = Jsons.parseList(value, GoodsFrontListView.class);
                 if (CollUtil.isNotEmpty(list)) {
+                    //设置特定价格
+                    setSpecificPrice(list, fUid);
                     return GatewayResponse.SUCCESS.newBuilder().toResult(list);
                 }
             } catch (Exception e) {
@@ -225,7 +234,7 @@ public class GoodsDonController {
         if (CollUtil.isNotEmpty(filter_goodsIds)) {
             builder.field(GoodsFrontListView::getId, filter_goodsIds).op(Operator.NotIn);
         }
-        List<GoodsHomePageView> dataList = beanSearcher.searchAll(GoodsHomePageView.class, builder.build());
+        List<GoodsFrontListView> dataList = beanSearcher.searchAll(GoodsFrontListView.class, builder.build());
         DateTime now = DateTime.now();
         dataList.forEach(data -> {
             Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
@@ -234,6 +243,8 @@ public class GoodsDonController {
             data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
         });
         redisService.setNx(h5CacheKey, dataList, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
+        //设置特定价格
+        setSpecificPrice(dataList, fUid);
         return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
     }
 
@@ -272,6 +283,8 @@ public class GoodsDonController {
      */
     @GetMapping("/get/{id}")
     public Result<GoodsDonViews> getDetail(@PathVariable Long id) {
+        Long userId = null;
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
         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()));
@@ -287,6 +300,13 @@ public class GoodsDonController {
                         .field(GoodsDiscountPlusPurchaseRelationFrontView::getSkuId, sku.getId())
                         .build()));
             }
+            if (fUid != null && views.getIsSp()) {
+                //设置特定价格
+                if (!isPaySpecificGoodsIds(sku.getSpecificGoodsIds(), fUid)) {
+                    sku.setSpecificGoodsIds(null);
+                    sku.setSpecificPrice(null);
+                }
+            }
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(views);
     }
@@ -295,11 +315,13 @@ public class GoodsDonController {
      * 获取商品推荐平台
      */
     @GetMapping("/get/recommend/{id}")
-    public Result<List<GoodsRecommendViews>> getRecommendGoodsByGid(@PathVariable Long id) throws Exception {
+    public Result<List<GoodsFrontListView>> getRecommendGoodsByGid(@PathVariable Long id) throws Exception {
         String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "recommend:" + id;
         Object value = redisService.get(key);
+        Long fUid = StpUserUtil.getUserIdAfterLogin();
         if (value != null) {
-            List<GoodsRecommendViews> goodsRecommendViews = Jsons.parseList(value.toString(), GoodsRecommendViews.class);
+            List<GoodsFrontListView> goodsRecommendViews = Jsons.parseList(value.toString(), GoodsFrontListView.class);
+            setSpecificPrice(goodsRecommendViews, fUid);
             return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
         }
         if (value == null) {
@@ -310,13 +332,15 @@ public class GoodsDonController {
                     .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());
-                goodsRecommendViews.forEach(data->{
+                List<GoodsFrontListView> goodsRecommendViews = beanSearcher.searchAll(GoodsFrontListView.class, MapUtils.builder().field(GoodsRecommendViews::getGoodsId, recommend_gidList).op(Operator.InList).build());
+                goodsRecommendViews.forEach(data -> {
                     Integer sold = registerOrderDonMapper.selectCount(Wrappers.lambdaQuery(RegisterOrderDon.class)
-                            .eq(RegisterOrderDon::getGoodsId, data.getGoodsId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
+                            .eq(RegisterOrderDon::getGoodsId, data.getId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
                     data.setSold(sold + data.getVirtualSold());
                 });
                 redisService.setNx(key, Jsons.toJson(goodsRecommendViews), 60 * 15l);
+                //设置特定价格
+                setSpecificPrice(goodsRecommendViews, fUid);
                 return GatewayResponse.SUCCESS.newBuilder().toResult(goodsRecommendViews);
             }
         }
@@ -418,4 +442,76 @@ public class GoodsDonController {
 	    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(List<GoodsFrontListView> list, Long fUid) {
+        if (fUid != null) {
+            list.forEach(data -> {
+                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 -> {
+                        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);
+                            }
+                        });
+                    }
+                }
+            });
+        }
+    }
 }

+ 34 - 0
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -3,6 +3,7 @@ package com.cyksj.web.controller.group;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.Assert;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.servlet.ServletUtil;
@@ -28,6 +29,7 @@ import com.cyksj.model.dto.QuestionnaireView;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.OrderPayRequest;
+import com.cyksj.model.request.SpecialGoodsTicketReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.ChatGptAuthService;
@@ -508,4 +510,36 @@ public class GroupRelationController {
         Page<UserRecommendGoodsFrontView> page = groupRelationFrontService.getRecommendGoodsViews(isPayNf, filter_goods_id, start, limit);
         return GatewayResponse.SUCCESS.newBuilder().toResult(page);
     }
+
+    /**
+     * 查看GPT token
+     */
+    @GetMapping("/get/gptAccessToken")
+    public Result<String> getGptAccessToken(Long relationId) throws Exception {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
+        //存在该车票
+        RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
+                .field(RenewalView::getRelationId, relationId)
+                .field(RenewalView::getUserId, userIds).op(Operator.InList).build());
+        Assert.notNull(renewalView, "您的车票不存在");
+        if (renewalView.getCategory() != 1) {
+            throw BusinessRuntimeException.getInstance("该平台类型车票无法获取GPT直连token");
+        }
+        String account = renewalView.getAccount();
+        String accessToken = chatGptAuthService.getAccessToken(account);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(accessToken);
+    }
+
+    /**
+     * 获取特殊类型课程 通过邮件发送课程
+     * 领取课件
+     */
+    @PostMapping("/courseware")
+    public Result<String> getCourseWare(@RequestBody SpecialGoodsTicketReq request) throws Exception {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        request.setUserId(userId);
+        groupRelationFrontService.sendCourseWare(request);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
 }

+ 3 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonController.java

@@ -98,6 +98,9 @@ public class CmsGoodsDonController {
     public Result<Long> spuInsert(@Validated @RequestBody ReqGoodsSpuInsert spu) throws Exception {
         // 新增商品
         GoodsDon goods = new GoodsDon();
+        if (spu.getSecondType() == null) {
+            spu.setSecondType(2);
+        }
         BeanUtil.copyProperties(spu, goods);
         if (StrUtil.isNotEmpty(goods.getRecommendTitle())) {
             if (CollUtil.isEmpty(spu.getRecommendGoodsList())) {

+ 19 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.manage.goods;
 
+import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
@@ -26,6 +27,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Set;
 
@@ -114,6 +116,23 @@ public class CmsGoodsDonSkuController {
         if (sku.getDays() == null) {
             sku.setDays(null);
         }
+        String specificGoodsIds = sku.getSpecificGoodsIds();
+        if (StrUtil.isEmpty(specificGoodsIds)) {
+            sku.setSpecificPrice(BigDecimal.ZERO);
+        } else {
+            Set<Long> specificGids = Jsons.parseSet(specificGoodsIds, Long.class);
+            Integer count = goodsDonService.count(Wrappers.lambdaQuery(GoodsDon.class)
+                    .in(GoodsDon::getId, specificGids)
+                    .eq(GoodsDon::getStatus, true)
+                    .eq(GoodsDon::getDeleted, true));
+            if (count != specificGids.size()) {
+                throw BusinessRuntimeException.getInstance("存在被删除或已下架的平台");
+            }
+            BigDecimal specificPrice = sku.getSpecificPrice();
+            if (specificPrice == null || specificPrice.compareTo(BigDecimal.ZERO) <= 0) {
+                throw BusinessRuntimeException.getInstance("请输入正确的特定价格");
+            }
+        }
         //优惠加购
         goodsDonSkuService.handleDiscountPurchaseGoods(sku, sku.getDpSku());
 

+ 3 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

@@ -112,7 +112,9 @@ public class DistributePopularizeController {
 			GoodsDon goodsDon = goodsDonMapper.selectById(data.getGoodsId());
 			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(data.getSkuId());
 			data.setGoodsTitle(goodsDon.getTitle());
-			data.setSpecVal(goodsDonSku.getSpecVal());
+			if (goodsDonSku != null) {
+				data.setSpecVal(goodsDonSku.getSpecVal());
+			}
 			data.setWaitGetMoney(data.getPoints().divide(points).multiply(money).divide(oneHundred));
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);

+ 7 - 0
netflix-web/src/main/java/com/cyksj/web/util/StpUserUtil.java

@@ -86,6 +86,13 @@ public class StpUserUtil {
         return stpLogic.isLogin();
     }
 
+    public static Long getUserIdAfterLogin() {
+        if (isLogin()) {
+            return StpUserUtil.getLoginIdAsLong();
+        }
+        return null;
+    }
+
     public static void checkLogin() {
         stpLogic.checkLogin();
     }