Просмотр исходного кода

Merge branch 'spotify_free_register' into dev

# Conflicts:
#	netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
chenbiao 2 лет назад
Родитель
Сommit
1a36f84942
74 измененных файлов с 1781 добавлено и 278 удалено
  1. 2 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 18 0
      netflix-common/src/main/java/com/cyksj/common/util/TicketCodeCommonUtil.java
  3. 6 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserConversationMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributeGeneralSkuRateMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributePosterGoodsMapper.java
  6. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  7. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptSession.java
  8. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/DistributeGeneralSkuRate.java
  9. 30 0
      netflix-dao/src/main/java/com/cyksj/model/entity/DistributePosterGoods.java
  10. 12 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTrips.java
  11. 0 2
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUserConversation.java
  12. 2 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/RegisterReq.java
  13. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  14. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java
  15. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderRefundReq.java
  16. 116 0
      netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java
  17. 17 12
      netflix-dao/src/main/java/com/cyksj/model/views/ChatgptCarInfoView.java
  18. 12 0
      netflix-dao/src/main/java/com/cyksj/model/views/ChatgptCarSessionView.java
  19. 39 0
      netflix-dao/src/main/java/com/cyksj/model/views/DisableAccountView.java
  20. 42 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePosterGoodsDetailView.java
  21. 52 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePosterGoodsFrontView.java
  22. 52 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePosterGoodsView.java
  23. 40 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuRateView.java
  24. 28 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserDetailView.java
  25. 59 0
      netflix-dao/src/main/java/com/cyksj/model/views/OrderDonUserRefundDetailView.java
  26. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  27. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/SysCorpFollowView.java
  28. 19 0
      netflix-dao/src/main/resources/mapper/MidjourneyUserConversationMapper.xml
  29. 1 1
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  30. 2 1
      netflix-service/src/main/java/com/cyksj/service/chatgpt/ChatGptAccountService.java
  31. 18 46
      netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java
  32. 5 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkService.java
  33. 24 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java
  34. 14 0
      netflix-service/src/main/java/com/cyksj/service/distribute/DistributePosterGoodsService.java
  35. 3 0
      netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java
  36. 47 0
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributePosterGoodsServiceImp.java
  37. 26 0
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  38. 1 1
      netflix-service/src/main/java/com/cyksj/service/mail/CuiQiuMailService.java
  39. 52 8
      netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java
  40. 0 2
      netflix-service/src/main/java/com/cyksj/service/mange/CmsOrderDonService.java
  41. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/MirrorUserCleatService.java
  42. 3 3
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsYhShopCommonServiceImpl.java
  43. 1 1
      netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java
  44. 17 37
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  45. 49 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/MirrorUserCleatServiceImpl.java
  46. 47 8
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java
  47. 0 1
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  48. 58 44
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  49. 11 1
      netflix-service/src/main/java/com/cyksj/service/paypal/PayPalService.java
  50. 1 1
      netflix-service/src/main/java/com/cyksj/service/register/RegisterOrderDonService.java
  51. 11 12
      netflix-service/src/main/java/com/cyksj/service/register/impl/RegisterOrderDonServiceImpl.java
  52. 1 1
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  53. 9 2
      netflix-service/src/main/java/com/cyksj/service/relation/GroupsRelationNetflixService.java
  54. 4 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java
  55. 85 12
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  56. 52 3
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java
  57. 10 0
      netflix-service/src/main/java/com/cyksj/service/stripe/StripeService.java
  58. 59 3
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpFollowServiceImpl.java
  59. 3 3
      netflix-web/src/main/java/com/cyksj/web/controller/external/ExternalController.java
  60. 30 34
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  61. 4 4
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  62. 116 3
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  63. 7 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java
  64. 38 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  65. 31 6
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java
  66. 114 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributePosterController.java
  67. 12 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java
  68. 23 4
      netflix-web/src/main/java/com/cyksj/web/controller/manage/statistics/StatisticsDataController.java
  69. 5 4
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java
  70. 12 12
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  71. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java
  72. 8 0
      netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java
  73. 17 2
      netflix-web/src/main/java/com/cyksj/web/controller/sys/SysCorpFollowController.java
  74. 105 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

+ 2 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -146,6 +146,8 @@ public interface Constant {
 
 	String CORP_SERVICE_FOLLOWS_KEY = "corp_service_follows_key";
 
+	String CORP_SERVICE_GROUPS_RELATION_FOLLOWS_KEY = "corp_service_groups_relation_follows_key";
+
 	String NEW_USER_WELFARE_KEY = "new_user_welfare_key";
 
 	/**

+ 18 - 0
netflix-common/src/main/java/com/cyksj/common/util/TicketCodeCommonUtil.java

@@ -2,6 +2,9 @@ package com.cyksj.common.util;
 
 import cn.hutool.core.util.StrUtil;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 /**
  * 项目名: yhlxj2
  * 文件名: TicketCodeCommonUtil
@@ -43,4 +46,19 @@ public class TicketCodeCommonUtil {
 		}
 		return code;
 	}
+
+	public static String extractUrl(String body, String prefixUrl) {
+		String urlPattern = "(https?://\\S+)";
+		Pattern pattern = Pattern.compile(urlPattern);
+		Matcher matcher = pattern.matcher(body);
+
+		// 查找匹配的URL
+		while (matcher.find()) {
+			String url = matcher.group();
+			if (url.contains(prefixUrl)) {
+				return url.replaceAll("\"", "");
+			}
+		}
+		return null;
+	}
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserConversationMapper.java

@@ -2,10 +2,16 @@ package com.cyksj.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.MidjourneyUserConversation;
+import com.cyksj.model.views.MidjourneyUserDetailView;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
 
 /**
  * @author zwhui
  * @date 2024/4/23 16:03
  */
 public interface MidjourneyUserConversationMapper extends BaseMapper<MidjourneyUserConversation> {
+
+	MidjourneyUserDetailView getMjMirrorOrderDetail(@Param("relationId") Long relationId, @Param("startTime") Date startTime, @Param("expiryTime") Date expiryTime);
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributeGeneralSkuRateMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.DistributeGeneralSkuRate;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributeGeneralSkuRateMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 14:05
+ */
+public interface DistributeGeneralSkuRateMapper extends BaseMapper<DistributeGeneralSkuRate> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributePosterGoodsMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.DistributePosterGoods;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 13:49
+ */
+public interface DistributePosterGoodsMapper extends BaseMapper<DistributePosterGoods> {
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/Account.java

@@ -102,4 +102,9 @@ public class Account extends BaseEntity {
      * 类型 1通用 2备用
      */
     private Integer type;
+
+    /**
+     * 账号是否禁用
+     */
+    private Boolean isDisable;
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptSession.java

@@ -66,5 +66,10 @@ public class ChatgptSession extends BaseEntity {
      */
     private String remark;
 
+    /**
+     * 分数
+     */
+    private Double score;
+
 
 }

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/DistributeGeneralSkuRate.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributeGeneralSkuRate
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 14:04
+ */
+
+@Getter
+@Setter
+public class DistributeGeneralSkuRate extends BaseEntity {
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Integer rate;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/DistributePosterGoods.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.entity;
+
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoods
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 13:48
+ */
+
+@Getter
+@Setter
+public class DistributePosterGoods extends BaseEntity{
+
+	private String name;
+
+	private Long goodsId;
+
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String skuIds;
+
+	private String img;
+
+	private Boolean status;
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsTrips.java

@@ -79,6 +79,14 @@ public class GroupsTrips {
     @DbField("sku.spec_val")
     @TableField(exist = false)
     private String specVal;
+
+    /**
+     * 商品规格
+     */
+    @DbField("sku.is_mirror")
+    @TableField(exist = false)
+    private Boolean isMirror;
+
     /**
      * 录入人
      */
@@ -126,6 +134,10 @@ public class GroupsTrips {
     @TableField(exist = false)
     private Date expiryTime;
 
+    @DbField("a.is_disable")
+    @TableField(exist = false)
+    private Boolean isDisable;
+
     /**
      * 车队上是否有人
      */

+ 0 - 2
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUserConversation.java

@@ -5,8 +5,6 @@ import lombok.Data;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
 
 /**
  * @author zwhui

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/RegisterReq.java

@@ -46,4 +46,6 @@ public class RegisterReq {
     private String appleRegisterType;
 
     private AppleAutoRegisterData.CountryOrArea countryOrArea;
+
+    private String code;
 }

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java

@@ -118,6 +118,9 @@ public class AccountView {
     @DbField("gdk.id")
     private Long skuId;
 
+    @DbField("gdk.is_mirror")
+    private Boolean isMirror;
+
     @DbField("a.gpt_refresh_token")
     private String gptRefreshToken;
 
@@ -155,4 +158,10 @@ public class AccountView {
 
     @DbField("a.type")
     private Integer accountType;
+
+    @DbIgnore
+    private Boolean isMjMirror;
+
+    @DbField("a.is_disable")
+    private Boolean isDisable;
 }

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

@@ -281,4 +281,10 @@ public class OrderDonBackView {
 	 */
 	@DbIgnore
 	private String serviceName;
+
+	@DbField("sku.mj_fast_num")
+	private Integer mjFastNum;
+
+	@DbField("sku.mj_relax_num")
+	private Integer mjRelaxNum;
 }

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

@@ -48,4 +48,9 @@ public class OrderRefundReq {
 	 * 聊天记录截图
 	 */
 	private String chatImg;
+
+	/**
+	 * 扣除的余额
+	 */
+	private BigDecimal deductBalance;
 }

+ 116 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java

@@ -0,0 +1,116 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsTrips;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: AccountDisableView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/1 16:29
+ */
+@Getter
+@Setter
+@SearchBean(tables = "account a left join goods_don g on a.goods_id = g.id " +
+		"left join groups_trips gt on gt.account_id = a.id " +
+		"left join goods_don_sku gdk on gdk.id = gt.sku_id")
+public class AccountDisableView {
+	@DbField("a.id")
+	private Long id;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.second_type")
+	private Integer goodsSecondType;
+
+	@DbField("a.bank_card")
+	private String bankCard;
+
+	@DbField("a.account")
+	private String account;
+
+	@DbField("a.password")
+	private String password;
+
+	@DbField("a.is_month")
+	private Boolean isMonth;
+
+	@DbField("a.api_key")
+	private String apiKey;
+
+	@DbField("a.gpt_email_pwd")
+	private String gptEmailPwd;
+
+	@DbField("a.verify_codes")
+	private String verifyCodes;
+
+	@DbField("a.api_secret")
+	private String apiSecret;
+
+	@DbField("a.start_time")
+	private Date startTime;
+
+	@DbField("a.expiry_time")
+	private Date expiryTime;
+
+	@DbField("a.amount")
+	private BigDecimal amount;
+
+	/**
+	 * 国区id
+	 */
+	@DbField("a.cn_account")
+	private String cnAccount;
+
+	/**
+	 * 美区id
+	 */
+	@DbField("a.us_account")
+	private String usAccount;
+
+	@DbField("a.customer_service_id")
+	private Long customerServiceId;
+
+	@DbField("a.secret")
+	private String secret;
+
+	@DbField("gt.id")
+	private Long groupsId;
+
+	@DbField("gt.status")
+	private GroupsTrips.Status gtStatus;
+
+	/**
+	 * 账号备注
+	 */
+	@DbField("a.remark")
+	private String remark;
+
+	@DbField("a.email")
+	private String email;
+
+	@DbField("gdk.id")
+	private Long skuId;
+
+	/**
+	 * 规格
+	 */
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("a.created_time")
+	private Date createdTime;
+
+	@DbField("a.is_disable")
+	private Boolean isDisable;
+}

+ 17 - 12
netflix-dao/src/main/java/com/cyksj/model/views/ChatgptCarInfoView.java

@@ -1,5 +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 lombok.Data;
 
 import java.util.Date;
@@ -10,61 +13,63 @@ import java.util.Objects;
  * @date 2024/4/8 17:02
  */
 @Data
+@SearchBean(
+        tables = "chatgpt_session cs"
+)
 public class ChatgptCarInfoView {
 
     /**
      * 车次id
      */
+    @DbField("cs.carId")
     private String carId;
 
     /**
      * 车次名称
      */
+    @DbField("cs.car_name")
     private String carName;
 
     /**
      * 车次状态 繁忙 空闲 停运
      */
-
+    @DbIgnore
     private String status;
 
 
     /**
      * 得分
      */
+    @DbField("cs.score")
     private Double score;
 
     /**
      * 可用时间
      */
+    @DbIgnore
     private Date expTime;
 
     /**
      * 车队可用时间
      */
+    @DbIgnore
     private Date teamExpTime;
 
     /**
      * 车次类型 team plus 3.5
      */
-
+    @DbIgnore
     private String type;
 
-    /**
-     * 限制次数
-     */
-    private Integer gptLimit;
-
     /**
      * 使用次数
      */
-
+    @DbIgnore
     private Integer use;
 
-    /**
-     * 是否为历史车次
-     */
-    private Boolean isHistory;
+    @DbField("cs.isPlus")
+    private Integer isPlus;
+
 
     @Override
     public boolean equals(Object o) {

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

@@ -55,6 +55,18 @@ public class ChatgptCarSessionView {
 	@DbField("cs.car_name")
 	private String carName;
 
+	/**
+	 * 官方session
+	 */
+	@DbField("cs.officialSession")
+	private String officialSession;
+
+	/**
+	 * 分数
+	 */
+	@DbField("cs.score")
+	private Double score;
+
 	/**
 	 * 备注
 	 */

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DisableAccountView.java

@@ -0,0 +1,39 @@
+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;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DisableAccountView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/28 13:42
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select goods_id,sku_id,account,any_value(created_time) as created_time from user_ticket_cleared_record where account != '' and source = 'disable' group by goods_id,sku_id,account) ur" +
+		" left join goods_don g on g.id = ur.goods_id" +
+		" left join goods_don_sku sku on sku.id = ur.sku_id")
+public class DisableAccountView {
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("ur.account")
+	private String account;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("ur.created_time")
+	private Date createdTime;
+}

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

@@ -0,0 +1,42 @@
+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;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 15:32
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "distribute_poster_goods dp inner join goods_don g on g.id = dp.goods_id",
+		where = "dp.status is true and g.status is true and g.deleted is true")
+public class DistributePosterGoodsDetailView {
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("dp.name")
+	private String name;
+
+	@DbField("dp.img")
+	private String img;
+
+	@DbField("dp.sku_ids")
+	private String skuIds;
+
+	@DbIgnore
+	private String nickname;
+
+	@DbField("g.rate")
+	private Integer rate;
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributePosterGoodsFrontView.java

@@ -0,0 +1,52 @@
+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.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsFrontView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 14:36
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "distribute_poster_goods dp inner join goods_don g on g.id = dp.goods_id",
+		where = "dp.status is true and g.status is true and g.deleted is true",
+		orderBy = "dp.update_time desc")
+public class DistributePosterGoodsFrontView {
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	/**
+	 * 推广名称
+	 */
+	@DbField("dp.name")
+	private String name;
+
+	@DbField("dp.img")
+	private String img;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("g.rate")
+	private Integer rate;
+
+	@DbField("g.is_sku_distribute")
+	private Boolean isSkuRate;
+
+	@DbField("g.min_price")
+	private BigDecimal price;
+
+	@DbField("dp.sku_ids")
+	private String skuIds;
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributePosterGoodsView.java

@@ -0,0 +1,52 @@
+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;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 15:48
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "distribute_poster_goods dp inner join goods_don g on g.id = dp.goods_id",
+		orderBy = "dp.update_time desc")
+public class DistributePosterGoodsView {
+	@DbField("dp.id")
+	private Long id;
+
+	@DbField("dp.name")
+	public String name;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("dp.sku_ids")
+	private String skuIds;
+
+	@DbIgnore
+	private String specVal;
+
+	@DbField("dp.img")
+	private String img;
+
+	@DbField("dp.status")
+	private Boolean status;
+
+	@DbField("dp.created_time")
+	private Date createdTIme;
+
+	@DbField("dp.update_time")
+	private Date updateTime;
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuRateView.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.views;
+
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsDonSkuRateView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 14:17
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "goods_don_sku sku inner join goods_don g on g.id = sku.goods_id" +
+		" left join distribute_general_sku_rate sr on sr.sku_id = sku.id",
+		where = "g.is_distribute is true and g.is_sku_distribute is true and g.type = 1 and g.status is true and g.deleted is true and sku.status is true",
+		orderBy = "sku.goods_id asc")
+public class GoodsDonSkuRateView {
+	@DbField("sr.id")
+	private Long id;
+
+	@DbField("sku.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("sr.rate")
+	private Integer rate;
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyUserDetailView.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyUserDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/6/25 15:26
+ */
+@Getter
+@Setter
+public class MidjourneyUserDetailView {
+	private Integer useFastNum;
+
+	private Integer useRelaxNum;
+
+	private Integer mjFastNum;
+
+	private Integer mjRelaxNum;
+
+	private Long userId;
+
+	private Date expiryTime;
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/views/OrderDonUserRefundDetailView.java

@@ -0,0 +1,59 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.OrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: OrderDonUserRefundDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/2 10:05
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don",
+		where = "status not in ('close','noPayment') :uid:")
+public class OrderDonUserRefundDetailView {
+	@DbField("count(1)")
+	private Integer orders;
+
+	@DbField("count(if(status = 'refund',1,NULL))")
+	private Integer refundOrders;
+
+
+	@Getter
+	@Setter
+	@SearchBean(tables = "order_don o left join goods_don g on g.id = o.goods_id" +
+			" left join goods_don_sku sku on sku.id = o.sku_id")
+	public static class OrderDonDetailView {
+		@DbField("o.user_id")
+		private Long userId;
+
+		@DbField("o.goods_id")
+		private Long goodsId;
+
+		@DbField("g.title")
+		private String title;
+
+		@DbField("sku.spec_val")
+		private String specVal;
+
+		@DbField("o.sku_id")
+		private Long skuId;
+
+		@DbField("ifnull(o.pay_time,o.created_time)")
+		private Date payTime;
+
+		@DbField("o.status")
+		private OrderDon.Status status;
+
+		@DbField("o.money")
+		private BigDecimal money;
+	}
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -257,4 +257,7 @@ public class RenewalView {
      */
     @DbIgnore
     private Boolean qa;
+
+    @DbIgnore
+    private DistributePosterGoodsDetailView posterInfo;
 }

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

@@ -54,6 +54,12 @@ public class SysCorpFollowView {
 	@DbIgnore
 	List<SysCorpFollowRelateView> subList;
 
+	/**
+	 * 是否开启企业会话
+	 */
+	@DbIgnore
+	private Boolean isOpen = false;
+
 	public String getShowName() {
 		StringBuilder sb = new StringBuilder();
 		sb.append(name).append("(").append(followName).append(")");

+ 19 - 0
netflix-dao/src/main/resources/mapper/MidjourneyUserConversationMapper.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.MidjourneyUserConversationMapper">
+
+
+    <select id="getMjMirrorOrderDetail" resultType="com.cyksj.model.views.MidjourneyUserDetailView">
+        select count(IF(muc.mode = 1, 1, NULL)) as useFastNum, count(if(muc.mode = 2, 1, NULL)) as useRelaxNum
+        from (select id from midjourney_user where relation_id = #{relationId} limit 1) mu
+        inner join midjourney_user_conversation muc on muc.user_id = mu.id
+        where muc.status in ('SUCCESS', 'IN_PROGRESS')
+        <if test="startTime != null">
+            and created_time > #{startTime}
+        </if>
+        <if test="expiryTime != null">
+            and created_time &lt; #{expiryTime}
+        </if>
+    </select>
+</mapper>

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

@@ -845,7 +845,7 @@ public class RedisService {
         MIDJOURNEY_RELAX_CONVERSATION("midjourney:relax:conversation:", "midjourney relax conversation", 60 * 60 * 2L),
         MIDJOURNEY_ACCOUNT_USED("midjourney:account:used:", "midjourney account used", 60 * 60 * 48L),
         APPLY_MONEY_DAY_LIMIT_KEY("apply_money_day_limit_key:%s:%s:%s", "每日提现次数限制", 60 * 60 * 24L),
-
+        NETFLIX_SET_LIMIT_TIME("netflix_set_limit_time", "奈飞设置限制", 30l),
         ;
 
         private String name;

+ 2 - 1
netflix-service/src/main/java/com/cyksj/service/chatgpt/ChatGptAccountService.java

@@ -9,6 +9,7 @@ import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
 
 import java.time.LocalDateTime;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -57,7 +58,7 @@ public interface ChatGptAccountService {
 
     ChatgptUser getCarChatGptUserWithToken(String userToken);
 
-    Set<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus);
+    List<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus);
 
     ChatGptUserView getUserInfo(long userId, Long relationId);
 

+ 18 - 46
netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java

@@ -697,22 +697,9 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
      * 获取车队信息
      */
     @Override
-    public Set<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus) {
-        SearchResult<ChatGptUserConversationRecordHistoryView> search = beanSearcher.search(ChatGptUserConversationRecordHistoryView.class, MapUtils.builder().field("userToken", userToken).limit(0, 2).build());
-        Set<ChatgptCarInfoView> res = search.getDataList().stream()
-                .map((historyView) -> {
-                    ChatgptCarInfoView chatgptCarInfoView = buildChatgptCarInfoView(historyView.getCarId(), historyView.getCarName(), historyView.getIsPLus(), redisService.zScore(RedisService.key.CHATGPT_CAR_SCORES.getName(), historyView.getCarId()));
-                    chatgptCarInfoView.setIsHistory(true);
-                    chatgptCarInfoView.setScore(Math.min(redisService.zScore(RedisService.key.CHATGPT_CAR_SCORES.getName(), historyView.getCarId()), 200));
-
-                    return chatgptCarInfoView;
-                }).collect(Collectors.toCollection(LinkedHashSet::new));
-
-        Set<ChatgptCarInfoView> lowestScoreFleets = getLowestScoreFleets(limit, isPlus);
-
-        res.addAll(lowestScoreFleets);
-
-        return res;
+    public List<ChatgptCarInfoView> getCarInfoList(String userToken, Integer limit, Boolean isPlus) {
+        List<ChatgptCarInfoView> lowestScoreFleets = getLowestScoreFleets(limit, isPlus);
+        return lowestScoreFleets;
     }
 
 
@@ -758,22 +745,11 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
 
 
     // 获取得分最低的N个车队的方法
-    public Set<ChatgptCarInfoView> getLowestScoreFleets(int count, Boolean isPlus) {
-        Set<ZSetOperations.TypedTuple<Object>> lowestScorecarIds;
-        Long fleetsSize = redisService.zCard(RedisService.key.CHATGPT_CAR_SCORES.getName());
-        // 构建ChatgptCarInfoView集合
-        if (fleetsSize != null && fleetsSize > 10) {
-            TASK_EXECUTOR.execute(() -> {
-                initFleets(true);
-            });
-        } else {
-            initFleets(false);
-        }
-        lowestScorecarIds = redisService.zRangeWithScores(RedisService.key.CHATGPT_CAR_SCORES.getName(), 0L, count - 1);
-        Map<Object, Double> collect = lowestScorecarIds.stream().collect(Collectors.toMap(ZSetOperations.TypedTuple::getValue, ZSetOperations.TypedTuple::getScore));
-        List<ChatgptSession> chatgptSessions = chatgptSessionMapper.selectList(Wrappers.lambdaQuery(ChatgptSession.class).in(ChatgptSession::getCarId, collect.keySet()).eq(isPlus !=null && isPlus, ChatgptSession::getIsPlus, true));
-        return chatgptSessions.stream().map((chatgptSession)-> buildChatgptCarInfoView(chatgptSession.getCarId(),chatgptSession.getCarName(), chatgptSession.getIsPlus(), collect.get(chatgptSession.getCarId())))
-                .sorted(Comparator.comparing(ChatgptCarInfoView::getScore)).collect(Collectors.toCollection(LinkedHashSet::new));
+    public List<ChatgptCarInfoView> getLowestScoreFleets(int count, Boolean isPlus) {
+        List<ChatgptCarInfoView> chatgptCarInfoViews = beanSearcher.searchList(ChatgptCarInfoView.class, MapUtils.builder().field(ChatgptCarInfoView::getIsPlus, isPlus).orderBy(ChatgptCarInfoView::getScore).asc().limit(0, count).build());
+
+        chatgptCarInfoViews.forEach(this::buildChatgptCarInfoView);
+        return chatgptCarInfoViews;
     }
 
     public void initFleets(Boolean flag) {
@@ -796,21 +772,18 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
 
 
     // 构建ChatgptCarInfoView对象
-    private ChatgptCarInfoView buildChatgptCarInfoView(String carId, String carName, Integer isPlus, Double score) {
+    private ChatgptCarInfoView buildChatgptCarInfoView(ChatgptCarInfoView view) {
         // 在这里根据carId获取相关信息并填充到ChatgptCarInfoView对象中
-        ChatgptCarInfoView view = new ChatgptCarInfoView();
-        view.setCarId(carId);
-        // 假设以下方法从Redis或其他服务获取数据
-        view.setScore(Math.min(score, 200));
-        view.setStatus(score >= 50 ? "繁忙" : "空闲"); // 或“繁忙”
 
-        if(carName.contains("T")){
+        view.setStatus(view.getScore() >= 50 ? "繁忙" : "空闲"); // 或“繁忙”
+
+        if(view.getCarName().contains("T") && view.getIsPlus() == 1){
             view.setType("Team");
-            Long team = carOaiLimit(carId, true);
+            Long team = carOaiLimit(view.getCarId(), true);
             if (team != 0L) {
                 view.setTeamExpTime(new DateTime(System.currentTimeMillis() + team * 1000));
             }
-            Long aLong = carOaiLimit(carId, false);
+            Long aLong = carOaiLimit(view.getCarId(), false);
             if (aLong != 0L) {
                 view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
             }
@@ -820,17 +793,16 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
                 view.setStatus("部分停运");
             }
         }else {
-            view.setType(isPlus == 1 ? "Plus" : "3.5");
-            Long aLong = carOaiLimit(carId, false);
+            view.setType(view.getIsPlus() == 1 ? "Plus" : "3.5");
+            Long aLong = carOaiLimit(view.getCarId(), false);
             if (aLong != 0L) {
                 view.setStatus("停运");
                 view.setExpTime(new DateTime(System.currentTimeMillis() + aLong * 1000));
             }
         }
-        int use = getCarConversationCount(carId, 3L).intValue();
+        int use = getCarConversationCount(view.getCarId(), 3L).intValue();
         view.setUse(use);
-
-        view.setCarName(carName);
+        view.setScore(Math.min(view.getScore(), 200));
         return view;
     }
 

+ 5 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpCustomerAcquisitionLinkService.java

@@ -19,4 +19,9 @@ public interface CorpCustomerAcquisitionLinkService extends IService<CorpCustome
     void del(Long id) throws Exception;
 
     void handleCorpLinkSchedulerJob() throws Exception;
+
+    /**
+     * 同步值班客服
+     */
+    void syncDutyLinkUrl() throws Exception;
 }

+ 24 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpCustomerAcquisitionLinkServiceImpl.java

@@ -1,15 +1,18 @@
 package com.cyksj.service.corp.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.SysCorpFollowRelateMapper;
 import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkMapper;
 import com.cyksj.mapper.corp.CorpCustomerAcquisitionLinkPopularizeMapper;
 import com.cyksj.model.entity.CorpCustomerAcquisitionLink;
 import com.cyksj.model.entity.CorpCustomerAcquisitionLinkPopularize;
+import com.cyksj.model.entity.SysCorpFollowRelate;
 import com.cyksj.model.request.corp.link.Range;
 import com.cyksj.model.request.corp.link.WxCpLinkAdd;
 import com.cyksj.model.request.corp.link.WxCpLinkAddResp;
@@ -26,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -42,6 +46,8 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
 
     private final SysCorpServiceRelateService sysCorpServiceRelateService;
 
+    private final SysCorpFollowRelateMapper sysCorpFollowRelateMapper;
+
     @Override
     @Transactional(rollbackFor = Throwable.class)
     public void add(CorpCustomerAcquisitionLink corpCustomerAcquisitionLink) throws Exception {
@@ -117,7 +123,10 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
 
         WxCpLinkUpd wxCpLinkUpd = new WxCpLinkUpd();
         wxCpLinkUpd.setLinkId(link.getLinkId());
-        WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionDeleteLink(null, wxCpLinkUpd);
+        try {
+            WxCpLinkAddResp wxCpLinkAddResp = corpOps.customerAcquisitionDeleteLink(null, wxCpLinkUpd);
+        } catch (Exception e) {
+        }
         removeById(id);
     }
 
@@ -126,4 +135,18 @@ public class CorpCustomerAcquisitionLinkServiceImpl extends ServiceImpl<CorpCust
         //立即执行客服值班定时任务
         XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.CORP_LINK_JOB_ID, StrUtil.EMPTY).toString());
     }
+
+    @Override
+    public void syncDutyLinkUrl() throws Exception {
+        //获取目前可用值班客服
+        List<SysCorpFollowRelate> sysCorpFollowRelates = sysCorpFollowRelateMapper.selectList(Wrappers.lambdaQuery(SysCorpFollowRelate.class)
+                .eq(SysCorpFollowRelate::getStatus, 1)
+                .eq(SysCorpFollowRelate::getDeleted, 1));
+        List<String> userIds = sysCorpFollowRelates.stream().map((e) -> e.getId().toString()).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(userIds)) {
+            this.update(Wrappers.lambdaUpdate(CorpCustomerAcquisitionLink.class)
+                    .set(CorpCustomerAcquisitionLink::getUserList, Jsons.toJson(userIds))
+                    .eq(CorpCustomerAcquisitionLink::getIsDuty, 1));
+        }
+    }
 }

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/DistributePosterGoodsService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.distribute;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.DistributePosterGoods;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsService
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 15:41
+ */
+public interface DistributePosterGoodsService extends IService<DistributePosterGoods> {
+	void saveOrUpdatePo(DistributePosterGoods distributePosterGoods) throws Exception;
+}

+ 3 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.distribute;
 
+import com.cyksj.model.entity.DistributeGeneralSkuRate;
 import com.cyksj.model.request.UserDistributeReq;
 
 import java.util.List;
@@ -29,4 +30,6 @@ public interface DistributeService {
 	void bindPopularizeCode(Long userId, String code);
 
 	void unbindUserDistributeShared(List<Object> userBind) throws Exception;
+
+	void setDistributeCommonSkuRate(List<DistributeGeneralSkuRate> skuRates);
 }

+ 47 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributePosterGoodsServiceImp.java

@@ -0,0 +1,47 @@
+package com.cyksj.service.distribute.impl;
+
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.manage.distribute.DistributePosterGoodsMapper;
+import com.cyksj.model.entity.DistributePosterGoods;
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.service.distribute.DistributePosterGoodsService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterGoodsServiceImp
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 15:42
+ */
+@Service
+@RequiredArgsConstructor
+public class DistributePosterGoodsServiceImp extends ServiceImpl<DistributePosterGoodsMapper, DistributePosterGoods> implements DistributePosterGoodsService {
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	@Override
+	public void saveOrUpdatePo(DistributePosterGoods distributePosterGoods) throws Exception {
+		Assert.notEmpty(distributePosterGoods.getImg(), "海报不为空");
+
+		Long goodsId = distributePosterGoods.getGoodsId();
+
+		GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+
+		if (goodsDon.getIsSkuDistribute()) {
+			if (StrUtil.isEmpty(distributePosterGoods.getSkuIds())) {
+				throw BusinessRuntimeException.getInstance("请选择对应的规格");
+			}
+			distributePosterGoods.setSkuIds(Jsons.toJson(Jsons.parseList(distributePosterGoods.getSkuIds(), String.class)));
+		} else {
+			distributePosterGoods.setSkuIds(null);
+		}
+
+		this.saveOrUpdate(distributePosterGoods);
+	}
+}

+ 26 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -36,6 +36,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 /*
  *项目名: netflix
@@ -81,6 +82,8 @@ public class DistributeServiceImpl implements DistributeService {
 
 	private final UserDistributeSubMapper userDistributeSubMapper;
 
+	private final DistributeGeneralSkuRateMapper generalSkuRateMapper;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void insertDistribute(UserDistributeReq userDistributeReq) {
@@ -379,6 +382,29 @@ public class DistributeServiceImpl implements DistributeService {
 		}
 	}
 
+	@Override
+	public void setDistributeCommonSkuRate(List<DistributeGeneralSkuRate> skuRates) {
+		List<Long> collect = skuRates.stream().map(DistributeGeneralSkuRate::getSkuId).collect(Collectors.toList());
+		if (CollUtil.isNotEmpty(collect)) {
+			generalSkuRateMapper.delete(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
+					.notIn(DistributeGeneralSkuRate::getSkuId, collect));
+		}
+		skuRates.forEach(e -> {
+			Integer rate = e.getRate();
+			if (rate == null || rate < 0 || rate > 100) {
+				throw BusinessRuntimeException.getInstance("请输入正确的比例");
+			}
+			if (e.getId() == null) {
+				try {
+					generalSkuRateMapper.insert(e);
+				} catch (DuplicateKeyException ex) {
+				}
+			} else {
+				generalSkuRateMapper.updateById(e);
+			}
+		});
+	}
+
 	public void checkDistributorAndBusinessRate(Integer distributeGoodsRate, Long goodsId, String goodsName) {
 		UserBusinessDefaultRateConfig defaultGoodsRateConfig = defaultRateConfigMapper.selectOne(Wrappers.lambdaQuery(UserBusinessDefaultRateConfig.class)
 				.eq(UserBusinessDefaultRateConfig::getGoodsId, goodsId)

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/mail/CuiQiuMailService.java

@@ -11,5 +11,5 @@ public interface CuiQiuMailService {
 	/**
 	 * 获取最新邮箱 返回验证码
 	 */
-	String getVerifyCode(String email, Long goodsId) throws Exception;
+	String getVerifyCode(String email, Long goodsId, Integer type, Boolean sync) throws Exception;
 }

+ 52 - 8
netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java

@@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
+import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.common.util.TicketCodeCommonUtil;
@@ -14,6 +15,8 @@ import com.cyksj.model.dto.CuiQiuEmailDetailDto;
 import com.cyksj.model.dto.CuiQiuEmailDto;
 import com.cyksj.model.dto.CuiQiuEmailResultDto;
 import com.cyksj.service.mail.CuiQiuMailService;
+import com.cyksj.service.relation.GroupsRelationNetflixService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
@@ -30,7 +33,10 @@ import java.util.stream.Collectors;
  */
 @Service
 @Slf4j
+@RequiredArgsConstructor
 public class CuiQiuMailServiceImpl implements CuiQiuMailService {
+	private final GroupsRelationNetflixService groupsRelationNetflix;
+
 	private final static String CUI_QIU_TOKEN = "4ff0341ebf1747cd89a2d1a5a296b68b";
 
 	//脆球域名id
@@ -44,8 +50,10 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 
 	private final static String DISNEY = "Disney+";
 
+	private final static String NETFLIX = "Netflix";
+
 	@Override
-	public String getVerifyCode(String email, Long goodsId) throws Exception {
+	public String getVerifyCode(String email, Long goodsId, Integer type, Boolean sync) throws Exception {
 		//获取近二十封邮件
 		String url = "https://domain-open-api.cuiqiu.com/v1/message/list";
 
@@ -65,6 +73,9 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		post.form(params);
 		HttpResponse execute = post.execute();
 		CuiQiuEmailResultDto resultDto = Jsons.parseObject(execute.body(), CuiQiuEmailResultDto.class);
+		if (resultDto.getData().getList() == null) {
+			return null;
+		}
 		List<CuiQiuEmailDto> list = resultDto.getData().getList();
 		//获取邮箱对应的邮件
 		list = list.stream().filter(emailInfo -> {
@@ -79,6 +90,9 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 				if (goodsId == 3l && StrUtil.equals(from.getName(), DISNEY)) {
 					return true;
 				}
+				if (goodsId == 1l && StrUtil.equals(from.getName(), NETFLIX)) {
+					return true;
+				}
 			}
 			return false;
 		}).collect(Collectors.toList());
@@ -87,7 +101,7 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 			for (CuiQiuEmailDto cuiQiuEmailDto : list) {
 				Long messageId = cuiQiuEmailDto.getId();
 				try {
-					String code = getVerifyCodeByEmail(messageId, goodsId);
+					String code = getVerifyCodeByEmail(messageId, goodsId, type, sync);
 					if (StrUtil.isNotBlank(code)) {
 						return code;
 					}
@@ -98,7 +112,7 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		return null;
 	}
 
-	public String getVerifyCodeByEmail(Long messageId, Long goodsId) throws Exception {
+	public String getVerifyCodeByEmail(Long messageId, Long goodsId, Integer type, Boolean sync) throws Exception {
 		String url = "https://domain-open-api.cuiqiu.com/v1/message/detail";
 		Map<String, Object> params = new HashMap<>();
 		params.put("token", CUI_QIU_TOKEN);
@@ -107,12 +121,42 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		HttpRequest post = HttpUtil.createPost(url);
 		post.form(params);
 		HttpResponse execute = post.execute();
-		String body = execute.body();
-		CuiQiuEmailDetailDto cuiQiuEmailDetailDto = Jsons.parseObject(body, CuiQiuEmailDetailDto.class);
+		String respBody = execute.body();
+		CuiQiuEmailDetailDto cuiQiuEmailDetailDto = Jsons.parseObject(respBody, CuiQiuEmailDetailDto.class);
 		CuiQiuEmailDetailDto.Content content = cuiQiuEmailDetailDto.getData().getContent();
-
-		String contentBody = content.getBody();
-		String code = TicketCodeCommonUtil.getTicketCodeStr(contentBody, goodsId);
+		String code = null;
+		String body = content.getBody();
+		if (goodsId == 1) {
+			if (type != null && type == 1) {
+				String pre = "NetflixSans-Regular, Helvetica, Roboto, Segoe UI, sans-serif; font-weight";
+				if (body.contains("輸入此代碼登入") || body.contains("输入此代码登录")) {
+					code = StrUtil.subAfter(body, pre, false);
+				}
+				if (StrUtil.isEmpty(code)) {
+					throw BusinessRuntimeException.getInstance("查询失败,请检查是否发送了登陆码..");
+				}
+			} else {
+				String urlPref = "https://www.netflix.com/account/update-primary-location";
+				String nfVerifyUrl = TicketCodeCommonUtil.extractUrl(body, urlPref);
+				if (StrUtil.isEmpty(nfVerifyUrl)) {
+					urlPref = "https://www.netflix.com/account/travel/verify";
+					nfVerifyUrl = TicketCodeCommonUtil.extractUrl(body, urlPref);
+					if (StrUtil.isEmpty(nfVerifyUrl)) {
+						throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
+					}
+				}
+				//非点击装置同步更新按钮 直接返回链接
+				if (!sync) return nfVerifyUrl;
+				//失败返回验证链接
+				if (!groupsRelationNetflix.confirmUpdate(nfVerifyUrl)) {
+					return nfVerifyUrl;
+				}
+				return StrUtil.EMPTY;
+			}
+		}
+		if (StrUtil.isEmpty(code)) {
+			code = TicketCodeCommonUtil.getTicketCodeStr(body, goodsId);
+		}
 		int length = 4;
 		if (goodsId == 33l) {
 			length = 6;

+ 0 - 2
netflix-service/src/main/java/com/cyksj/service/mange/CmsOrderDonService.java

@@ -57,6 +57,4 @@ public interface CmsOrderDonService extends IService<OrderDon> {
 	void refundPriceDiffer(OrderRefundReq orderRefundReq) throws Exception;
 
 	void clearBalanceToRefundMoney(OrderBalanceRefundReq refundReq) throws Exception;
-
-	void delMirrorUser(Long goodsId, Long relationId);
 }

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

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MirrorUserCleatService
+ * 创建者: JavaZou
+ * 创建时间:2024/6/27 11:15
+ */
+public interface MirrorUserCleatService {
+	void delMirrorUser(Long goodsId, Long relationId);
+}

+ 3 - 3
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsYhShopCommonServiceImpl.java

@@ -190,9 +190,9 @@ public class CmsYhShopCommonServiceImpl implements CmsYhShopCommonService {
 			log.info("店铺提现审核失败,归还店铺申请提现金额:{}至用户{}结束", distributeMoneyApply.getMoney().divide(BigDecimal.valueOf(100)), userId);
 		}
 		if (YhShopDistributeMoneyApply.Status.success.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
-			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
-				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
-			}
+//			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
+//				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
+//			}
 			distributeMoneyApply.setImg(distributeApplyMoneyReq.getImg());
 		}
 		yhShopDistributeMoneyApplyMapper.updateById(distributeMoneyApply);

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java

@@ -264,7 +264,7 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             //设置奈飞用户座位
             if (account.getGoodsId() == 1) {
                 User user = userMapper.selectById(relation.getUserId());
-                groupsRelationNetflixService.setNetflixSeatNum(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime());
+	            groupsRelationNetflixService.timingSetNetflix(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime());
             }
         }
         if (groupsRelations.isEmpty() && verifyCodeList != null && verifyCodeList.size() > 0) {

+ 17 - 37
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -51,6 +51,7 @@ import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.giftcard.GiftCardOrderUseRecordService;
 import com.cyksj.service.mange.CmsOrderDonService;
+import com.cyksj.service.mange.MirrorUserCleatService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
 import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.service.order.OrderCommonService;
@@ -193,6 +194,8 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final AccountMapper accountMapper;
 
+    private final MirrorUserCleatService mirrorUserCleatService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -358,10 +361,13 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             return;
         }
         //调用第三方接口退款
-        String outNo = orderRefundService.centerRefund(refundReq, orderDon);
+        String outNo = StrUtil.EMPTY;
+        if (refundReq.getRefundMoney() != null && refundReq.getRefundMoney().compareTo(BigDecimal.ZERO) > 0) {
+            outNo = orderRefundService.centerRefund(refundReq, orderDon);
+        }
         orderDon.setRefundDesc(refundReq.getRefundDesc());
         //记录退款信息
-        commonRefund(orderDon, refundReq.getRefundMoney(), refundReq.getOperator(), goodsDon, sku, outNo, refundType, refundReq.getIsOnly(), refundReq.getRefundBalance(), refundReq.getChatImg());
+        commonRefund(orderDon, refundReq.getRefundMoney(), refundReq.getOperator(), goodsDon, sku, outNo, refundType, refundReq.getIsOnly(), refundReq.getRefundBalance(), refundReq.getChatImg(), refundReq.getDeductBalance());
         //修改订单状态
         orderDon.setStatus(OrderDon.Status.refund);
         orderDonMapper.updateById(orderDon);
@@ -690,17 +696,12 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         relation.setNewRelationId(newRelation.getId());
         relationClearService.clearTicket(relation, source);
 
-        //是否是GPT镜像规格
-        if (orderDon.getOrderType() == 1) {
-            delMirrorUser(orderDon.getGoodsId(), orderDon.getRelationId());
-        }
-
         //奈飞车票
         if (orderDon.getGoodsId() == 1) {
             User user = userMapper.selectById(newRelation.getUserId());
             GroupsTrips groupsTrips = groupsMapper.selectById(newRelation.getGroupsId());
             Account account = accountMapper.selectById(groupsTrips.getAccountId());
-            groupsRelationNetflixService.setNetflixSeatNum(newRelation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), newRelation.getExpiryTime());
+	        groupsRelationNetflixService.timingSetNetflix(newRelation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), newRelation.getExpiryTime());
         }
 
         if (plusPurchaseSkuRelation != null && plus_relationList != null) {
@@ -911,7 +912,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
     /**
      * 退款后 处理关联
      */
-    public void commonRefund(OrderDon orderDon, BigDecimal refundMoney, String operator, GoodsDon goodsDon, GoodsDonSku sku, String outNo, String refundType, Boolean isOnly, BigDecimal refundBalance, String chatImg) {
+    public void commonRefund(OrderDon orderDon, BigDecimal refundMoney, String operator, GoodsDon goodsDon, GoodsDonSku sku, String outNo, String refundType, Boolean isOnly, BigDecimal refundBalance, String chatImg, BigDecimal deductBalance) {
         TASK_POOL.execute(() -> {
             orderRefundService.refundRecord(orderDon, refundMoney, operator, goodsDon, sku, outNo, refundType, chatImg);
             //退款一次
@@ -935,7 +936,12 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
             //若存在余额支付,退还余额
             if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-                userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.refund, orderDon.getYhsId(), orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
+                BigDecimal addBalance = orderDon.getBalance();
+                //需额外扣除余额
+                if (deductBalance != null && deductBalance.compareTo(BigDecimal.ZERO) > 0) {
+                    addBalance = addBalance.subtract(deductBalance);
+                }
+                userBenefitsService.addUserBalance(orderDon.getUserId(), addBalance, UserBalanceSourceRecord.Source.refund, orderDon.getYhsId(), orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
             }
 
             try {
@@ -1051,7 +1057,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             }
             //是否是GPT镜像规格
             if (orderDon.getOrderType() == 1) {
-                delMirrorUser(orderDon.getGoodsId(), orderDon.getRelationId());
+                mirrorUserCleatService.delMirrorUser(orderDon.getGoodsId(), orderDon.getRelationId());
             }
             //是否是分销订单
             //处理下级渠道分销提成
@@ -1329,30 +1335,4 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         }
         return relation;
     }
-
-    /**
-     * 删除gptUser
-     */
-    @Override
-    public void delMirrorUser(Long goodsId, Long relationId) {
-        //gpt镜像
-        if (goodsId != null && goodsId == 18) {
-            Integer selectCount = chatgptUserMapper.selectCount(Wrappers.lambdaQuery(ChatgptUser.class)
-                    .eq(ChatgptUser::getRelationId, relationId));
-            if (selectCount > 0) {
-                chatgptUserMapper.delete(Wrappers.lambdaQuery(ChatgptUser.class)
-                        .eq(ChatgptUser::getRelationId, relationId));
-            }
-        }
-        //mj镜像
-        if (goodsId != null && goodsId == 26) {
-            MidjourneyUser user = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
-                    .eq(MidjourneyUser::getRelationId, relationId).last("limit 1"));
-            if (user != null) {
-                midjourneyUserMapper.delete(Wrappers.lambdaQuery(MidjourneyUser.class)
-                        .eq(MidjourneyUser::getRelationId, relationId));
-                redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + user.getUserToken());
-            }
-        }
-    }
 }

+ 49 - 0
netflix-service/src/main/java/com/cyksj/service/mange/impl/MirrorUserCleatServiceImpl.java

@@ -0,0 +1,49 @@
+package com.cyksj.service.mange.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.mapper.ChatgptUserMapper;
+import com.cyksj.mapper.MidjourneyUserMapper;
+import com.cyksj.model.entity.ChatgptUser;
+import com.cyksj.model.entity.MidjourneyUser;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.MirrorUserCleatService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MirrorUserCleatServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/6/27 11:15
+ */
+@Service
+@RequiredArgsConstructor
+public class MirrorUserCleatServiceImpl implements MirrorUserCleatService {
+	private final ChatgptUserMapper chatgptUserMapper;
+
+	private final MidjourneyUserMapper midjourneyUserMapper;
+
+	private final RedisService redisService;
+	@Override
+	public void delMirrorUser(Long goodsId, Long relationId) {
+		//gpt镜像
+		if (goodsId != null && goodsId == 18) {
+			Integer selectCount = chatgptUserMapper.selectCount(Wrappers.lambdaQuery(ChatgptUser.class)
+					.eq(ChatgptUser::getRelationId, relationId));
+			if (selectCount > 0) {
+				chatgptUserMapper.delete(Wrappers.lambdaQuery(ChatgptUser.class)
+						.eq(ChatgptUser::getRelationId, relationId));
+			}
+		}
+		//mj镜像
+		if (goodsId != null && goodsId == 26) {
+			MidjourneyUser user = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+					.eq(MidjourneyUser::getRelationId, relationId).last("limit 1"));
+			if (user != null) {
+				midjourneyUserMapper.delete(Wrappers.lambdaQuery(MidjourneyUser.class)
+						.eq(MidjourneyUser::getRelationId, relationId));
+				redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + user.getUserToken());
+			}
+		}
+	}
+}

+ 47 - 8
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.midjourney.impl;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.lang.UUID;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.http.HttpRequest;
@@ -18,6 +19,7 @@ import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.user.UserBindRelationService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -25,9 +27,7 @@ import javax.imageio.stream.FileImageOutputStream;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * @author zwhui
@@ -136,13 +136,49 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
             throw BusinessRuntimeException.getInstance("addAccount error message:" + jsonObject.getStr("description"));
         }
     }
-
+    private static final List<String> User_Agent_LIST =  List.of(
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
+            "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
+            "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
+            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
+            "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
+            "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
+            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
+            "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
+            "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
+            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
+            "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
+            "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
+            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
+            "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
+            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
+            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
+            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
+            "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
+            "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
+            "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
+            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
+            "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10");
     private Map<String, Object> createAccountParam(MidjourneyAccount midjourneyAccount) {
         Map<String, Object> param = new HashMap<>();
         param.put("channelId", midjourneyAccount.getChannelId());
         param.put("guildId", midjourneyAccount.getGuildId());
         param.put("userToken", midjourneyAccount.getUserToken());
         param.put("remark", midjourneyAccount.getId());
+        param.put("userAgent", User_Agent_LIST.get(new Random().nextInt(User_Agent_LIST.size())));
+        param.put("timeoutMinutes", 10);
         return param;
     }
 
@@ -257,11 +293,14 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
             midjourneyUser.setMjRelaxNum((goodsDonSku.getMjRelaxNum() == null || goodsDonSku.getMjRelaxNum() == 0) ? null : goodsDonSku.getMjRelaxNum());
         }
         midjourneyUser.setAqType(groupsRelation.getAqType());
-        midjourneyUserMapper.insert(midjourneyUser);
-        redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(),RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
-        redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser,RedisService.key.MIDJOURNEY_USER.getTimeout());
+        try {
+            midjourneyUserMapper.insert(midjourneyUser);
+        } catch (DuplicateKeyException e) {
+        }
+        redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
+        redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser, RedisService.key.MIDJOURNEY_USER.getTimeout());
         if (midjourneyUser.getMjRelaxNum() != null) {
-            redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(),RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
+            redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
         }
         return midjourneyUser;
     }

+ 0 - 1
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -14,7 +14,6 @@ import com.cyksj.model.entity.UpgradeOrderDon;
 import com.cyksj.model.manage.views.UpgradeOrderDetailView;
 import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.OrderPayRequest;
-import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 import java.util.List;

+ 58 - 44
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -315,6 +315,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final OrderDonExceptionUserRecordMapper orderDonExceptionUserRecordMapper;
 
+	private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -1152,14 +1154,16 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 
 		if (orderDon.getOrderType() == 1 && StrUtil.isNotEmpty(buyerId)) {
-			//近一个月同一买家id 只能购买一次 多人
-			if (orderDon.getGoodsId() == 26l && sku.getNum() != 1) {
+			//近一个月同一买家id 只能购买一次 多人 非镜像
+			if (orderDon.getGoodsId() == 26l && sku.getNum() != 1 && !sku.getIsMirror()) {
+				List<Long> userIdList = userBindRelationService.getRelationUserIdList(orderDon.getUserId(), null);
 				Integer count = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
 						.ne(OrderDon::getId, orderDon.getId())
 						.eq(OrderDon::getGoodsId, orderDon.getGoodsId())
-						.eq(OrderDon::getBuyerId, buyerId)
 						.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
-						.ge(OrderDon::getCreatedTime, DateUtil.offsetMonth(DateTime.now(), -1)));
+						.ge(OrderDon::getCreatedTime, DateUtil.offsetMonth(DateTime.now(), -1))
+						//同一买家或者同一用户
+						.and(o -> o.eq(OrderDon::getBuyerId, buyerId).or().in(OrderDon::getUserId, userIdList)));
 				if (count > 1) {
 					//退款
 					log.info("一个月内同一买家id购买过Midjourney账号,对订单号:{}进行退款", orderDon.getOrderNo());
@@ -1527,6 +1531,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			log.info("分销订单orderId:{}对应平台goodsId:{}不存在或已不参与分成比例", order.getId(), order.getGoodsId());
 			return;
 		}
+		if (order.getSkuId() != null) {
+			goodsDonSku = goodsDonSkuMapper.selectById(order.getSkuId());
+		}
 		UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, order.getUserId()).last("limit 1"));
 		if (userDistributeShared != null) {
 			distributeWaitingSendPoints.setSharedId(userDistributeShared.getSharedId());
@@ -1550,7 +1557,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					rate = goodsDon.getRate();
 					//实物分销比例
 					if (goodsDon.getType() == 2) {
-						goodsDonSku = goodsDonSkuMapper.selectById(order.getSkuId());
 						if (goodsDonSku != null) {
 							//不包含套餐权益
 							if (!goodsDonSku.getIsBenefits()) {
@@ -1558,6 +1564,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 							}
 						}
 					}
+					//该平台是否开启规格分销
+					if (goodsDon.getIsSkuDistribute()) {
+						//是否设置对应规格分销比例
+						DistributeGeneralSkuRate skuRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
+								.eq(DistributeGeneralSkuRate::getSkuId, goodsDonSku.getId()).last("limit 1"));
+						if (skuRate != null) rate = skuRate.getRate();
+					}
 					returnMoney = orderMoney.multiply(BigDecimal.valueOf(rate)).divide(BigDecimal.valueOf(100));
 				} else {
 					businessId = userDistribute.getBusinessId();
@@ -2270,49 +2283,50 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//特殊渠道推广优惠. 360
 		if (subsidyId == null && orderDon.getPopularizeId() != null && orderDon.getPopularizeId() != 0L) {
 			String name = channelPopularizeMapper.selectChannelByPid(orderDon.getPopularizeId());
-			//使用了优惠券 不再使用360渠道 折扣
-			if (couponUser == null && goodsType == 1) {
-				if (name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(0)) || name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(1))) {
-					String key;
-					if (name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(0))) {
-						//百度渠道 专门优惠链接
-						key = Constant.CHANNEL_BAIDU_DISCOUNT_KEY;
-					} else {
-						//抖音
-						key = Constant.CHANNEL_DY_DISCOUNT_KEY;
-					}
-					SysConfig channelNoSignConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
-							.eq(SysConfig::getSysKey, key).last("limit 1"));
-					if (channelNoSignConfig != null) {
-						String sysValue = channelNoSignConfig.getSysValue();
-						if (StrUtil.isNotBlank(sysValue)) {
-							try {
-								ChannelBaiDuDiscountDto baiDuDiscountDto = Jsons.parseObject(sysValue, ChannelBaiDuDiscountDto.class);
-								List<Long> baiduPopularizeIds = baiDuDiscountDto.getPopularizeIds();
-								BigDecimal discount = baiDuDiscountDto.getDiscount();
-								if (CollUtil.isNotEmpty(baiduPopularizeIds) && discount != null && discount.compareTo(BigDecimal.ZERO) > 0) {
-									if (baiduPopularizeIds.contains(orderDon.getPopularizeId())) {
-										BigDecimal discountMoney = orderDon.getMoney().multiply(discount);
-										orderDon.setMoney(discountMoney);
+			if (StrUtil.isNotBlank(name)) {
+				//使用了优惠券 不再使用360渠道 折扣
+				if (couponUser == null && goodsType == 1) {
+					if (name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(0)) || name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(1))) {
+						String key;
+						if (name.contains(Constant.NO_SIGN_CHANNEL_NAMES.get(0))) {
+							//百度渠道 专门优惠链接
+							key = Constant.CHANNEL_BAIDU_DISCOUNT_KEY;
+						} else {
+							//抖音
+							key = Constant.CHANNEL_DY_DISCOUNT_KEY;
+						}
+						SysConfig channelNoSignConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+								.eq(SysConfig::getSysKey, key).last("limit 1"));
+						if (channelNoSignConfig != null) {
+							String sysValue = channelNoSignConfig.getSysValue();
+							if (StrUtil.isNotBlank(sysValue)) {
+								try {
+									ChannelBaiDuDiscountDto baiDuDiscountDto = Jsons.parseObject(sysValue, ChannelBaiDuDiscountDto.class);
+									List<Long> baiduPopularizeIds = baiDuDiscountDto.getPopularizeIds();
+									BigDecimal discount = baiDuDiscountDto.getDiscount();
+									if (CollUtil.isNotEmpty(baiduPopularizeIds) && discount != null && discount.compareTo(BigDecimal.ZERO) > 0) {
+										if (baiduPopularizeIds.contains(orderDon.getPopularizeId())) {
+											BigDecimal discountMoney = orderDon.getMoney().multiply(discount);
+											orderDon.setMoney(discountMoney);
+										}
 									}
-								}
 
-							} catch (Exception e) {
+								} catch (Exception e) {
+								}
 							}
 						}
 					}
-				}
-			} else {
-				//360
-				if (Constant.CHANNEL_NAME_360.equals(name)) {
-					SysConfig sysConfig = sysConfigService.getBaseMapper().selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.CHANNEL_360_DISCOUNT));
-					if (sysConfig != null) {
-						BigDecimal discountMoney = orderDon.getMoney().multiply(BigDecimal.valueOf(Double.valueOf(sysConfig.getSysValue())));
-						orderDon.setMoney(discountMoney);
+				} else {
+					//360
+					if (Constant.CHANNEL_NAME_360.equals(name)) {
+						SysConfig sysConfig = sysConfigService.getBaseMapper().selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.CHANNEL_360_DISCOUNT));
+						if (sysConfig != null) {
+							BigDecimal discountMoney = orderDon.getMoney().multiply(BigDecimal.valueOf(Double.valueOf(sysConfig.getSysValue())));
+							orderDon.setMoney(discountMoney);
+						}
 					}
 				}
 			}
-
 		}
 		//存在余额
 		deductBalancePayOrderMoney(orderDon, balance, user);
@@ -2328,6 +2342,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		} else {
 			//修改车位状态并发送模板消息
 			updateCarParkAndSendMsg(goodsDon, sku, orderDon);
+		}
+		//同步车票是否重购 记录
+		TASK_POOL.execute(() -> {
 			if (goodsDon.getId() == 1) {
 				//设置netflix座位号
 				GroupsRelation relation = groupsRelationMapper.selectById(orderDon.getRelationId());
@@ -2335,12 +2352,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				if (groupsTrips.getStatus() != GroupsTrips.Status.waiting) {
 					Account account = accountMapper.selectById(groupsTrips.getAccountId());
 					User user = userMapper.selectById(relation.getUserId());
-					groupsRelationNetflixService.setNetflixSeatNum(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime());
+					groupsRelationNetflixService.timingSetNetflix(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime());
 				}
 			}
-		}
-		//同步车票是否重购 记录
-		TASK_POOL.execute(() -> {
 			groupsRelationExpiryRecordService.syncGroupsRelationExpiryRecord(orderDon, goodsDon, sku);
 			if (orderDon.getYhsId() == 0) {
 				//发送下单后 若有手机 发送短信

+ 11 - 1
netflix-service/src/main/java/com/cyksj/service/paypal/PayPalService.java

@@ -4,13 +4,15 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.PaypalPayConfig;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.order.OrderDonService;
-import com.paypal.api.payments.*;
 import com.paypal.api.payments.Currency;
+import com.paypal.api.payments.*;
 import com.paypal.base.rest.APIContext;
 import com.paypal.base.rest.OAuthTokenCredential;
 import com.paypal.base.rest.PayPalRESTException;
@@ -44,6 +46,8 @@ public class PayPalService{
 
     private final RedisService redisService;
 
+    private final GoodsDonSkuMapper skuMapper;
+
 
     private static final String SANDBOX_URL = "https://api-m.sandbox.paypal.com";
     private static final String LIVE_URL = "https://api-m.paypal.com";
@@ -112,6 +116,12 @@ public class PayPalService{
 
     public Payment createPayment(Long orderId,String successUrl) throws PayPalRESTException {
         OrderDon orderDon = orderDonService.getById(orderId);
+        if (orderDon.getGoodsId() == 26) {
+            GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+            if (!sku.getIsMirror()) {
+                throw BusinessRuntimeException.getInstance("订单异常..");
+            }
+        }
         //paypal 不能购买奈飞月付账号 24-1-23
         if (orderDon.getSkuId() != null && orderDon.getSkuId() == 4) {
             throw BusinessRuntimeException.getInstance("暂不支持paypal购买该规格车票..");

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/register/RegisterOrderDonService.java

@@ -19,7 +19,7 @@ import java.util.Map;
  */
 public interface RegisterOrderDonService extends IService<RegisterOrderDon> {
 
-    boolean isFree(long userId, String platform);
+    boolean isFree(long userId, String platform, String code);
 
     RegisterOrderDon saveOrder(long userId, RegisterReq req, boolean isFree) throws Exception;
 

+ 11 - 12
netflix-service/src/main/java/com/cyksj/service/register/impl/RegisterOrderDonServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import com.alipay.api.AlipayClient;
 import com.alipay.api.domain.AlipayTradeRefundModel;
 import com.alipay.api.internal.util.AlipaySignature;
@@ -112,21 +113,19 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
      * @date 2022-11-07 3:34 PM
      */
     @Override
-    public boolean isFree(long userId, String platform) {
-        int count = count(Wrappers.lambdaQuery(RegisterOrderDon.class)
-                .eq(RegisterOrderDon::getUserId, userId)
-                .ne(RegisterOrderDon::getStatus, RegisterOrderDon.Status.noPayment)
-                .eq(RegisterOrderDon::getIsFree, true));
-        if(count > 0){
+    public boolean isFree(long userId, String platform, String code) {
+
+        SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "spotify_free_code"));
+        if (sysConfig == null) {
             return false;
-        }
-        Long num = redisService.decr(RedisKey.SPOTIFY_FREE_NUM, 1L);
-        if(num >= 0){
-            return true;
         }else {
-            redisService.incr(RedisKey.SPOTIFY_FREE_NUM, 1L);
+            if (JSONUtil.isJsonArray(sysConfig.getSysValue())) {
+                List<String> list = JSONUtil.parseArray(sysConfig.getSysValue()).toList(String.class);
+                return list.contains(code);
+            }else {
+                return false;
+            }
         }
-        return false;
     }
 
     /**

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

@@ -38,7 +38,7 @@ public interface GroupRelationFrontService {
 	/**
 	 * 获取车票账号登录 验证码
 	 */
-	String getAiVerifyCode(Long userId, Long relationId, Integer type) throws Exception;
+	String getAiVerifyCode(Long userId, Long relationId, Integer type, Boolean sync) throws Exception;
 
 
 	void checkGroupsAvailParkingNum(Long skuId, Long groupsId, Integer availableParkingNum, Integer maxNum);

+ 9 - 2
netflix-service/src/main/java/com/cyksj/service/relation/GroupsRelationNetflixService.java

@@ -12,9 +12,16 @@ import java.util.Date;
  */
 public interface GroupsRelationNetflixService {
 
-	JSONObject setNetflixSeatNum(Integer seatNum, String seatName, String account, String password, Date expiryTime);
+	JSONObject setNetflixSeatNum(Integer seatNum, String seatName, String account, String password, Date expiryTime, String code);
 
-	JSONObject setNetflixPin(Long relationId, long userId);
+	JSONObject setNetflixPin(Long relationId, long userId, String code);
 
 	Integer getPinStatus(String taskId) throws Exception;
+
+	Boolean confirmUpdate(String nfUrl);
+
+	/**
+	 * 定时设置奈飞座位号
+	 */
+	void timingSetNetflix(Integer num, String nickname, String account, String password, Date expiryTime);
 }

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java

@@ -8,6 +8,7 @@ import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.entity.UserTicketClearedRecord;
 import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.service.mange.MirrorUserCleatService;
 import com.cyksj.service.relation.GroupRelationClearService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.util.MapUtils;
@@ -38,6 +39,8 @@ public class GroupRelationClearServiceImpl implements GroupRelationClearService
 
 	private final GoodsDonSkuMapper goodsDonSkuMapper;
 
+	private final MirrorUserCleatService mirrorUserCleatService;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void clearTicket(GroupsRelation relation, UserTicketClearedRecord.Source source) {
@@ -125,6 +128,7 @@ public class GroupRelationClearServiceImpl implements GroupRelationClearService
 //						log.info("ChatGPT 独立会员账号车票过期,删除原先车队id:{}并生成一个10人月付规格的车队id:{}", groupsRelation.getId(), gt.getId());
 //					}
 //				}
+				mirrorUserCleatService.delMirrorUser(groupsRelation.getGoodsId(), groupsRelation.getId());
 			}
 		}
 	}

+ 85 - 12
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -21,6 +21,10 @@ import com.cyksj.common.util.StringUtil;
 import com.cyksj.common.util.TicketCodeCommonUtil;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.manage.distribute.DistributeGeneralSkuRateMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper;
+import com.cyksj.mapper.manage.distribute.UserPlatSkuDistributeRateMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.SpecialGoodsTicketReq;
@@ -34,6 +38,7 @@ import com.cyksj.service.mail.MailService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.relation.GroupRelationFrontService;
+import com.cyksj.service.relation.GroupsRelationNetflixService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.user.UserLoginRecordService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -125,6 +130,18 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final GoodsDonQaRelateMapper goodsDonQaRelateMapper;
 
+	private final GroupsRelationNetflixService groupsRelationNetflixService;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final UserPlatDistributeRateMapper userPlatDistributeRateMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final UserPlatSkuDistributeRateMapper userPlatSkuDistributeRateMapper;
+
+	private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
+
 	@Override
 	public SearchResult<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account) {
 		User u = userMapper.selectById(userId);
@@ -294,6 +311,8 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			}
 			Long qaId = groupsRelationMapper.selectGoodsDonQaByGoodsId(ticket.getGoodsId());
 			ticket.setQa(qaId > 0 ? true : false);
+			//是否存在海报
+			ticket.setPosterInfo(setGoodsPoster(ticket, u));
 		});
 		userLoginRecordService.saveUserLoginDayRecord(userId);
 		return list;
@@ -497,7 +516,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	}
 
 	@Override
-	public String getAiVerifyCode(Long userId, Long relationId, Integer type) throws Exception {
+	public String getAiVerifyCode(Long userId, Long relationId, Integer type, Boolean sync) throws Exception {
 		List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
 		RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
 				.field(RenewalView::getRelationId, relationId).build());
@@ -513,7 +532,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服...");
 		}
 		if (renewalView.getAccount().contains(CUI_QIU_EMAIL_SUFFIX)) {
-			return cuiQiuMailService.getVerifyCode(renewalView.getAccount(), renewalView.getGoodsId());
+			return cuiQiuMailService.getVerifyCode(renewalView.getAccount(), renewalView.getGoodsId(), type, sync);
 		}
 		//获取邮箱密码
 		SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
@@ -541,7 +560,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		if (execute.getStatus() != HttpStatus.HTTP_OK) {
 			throw BusinessRuntimeException.getInstance("获取验证码异常,请联系客服...");
 		}
-		String code = getDifferentGoodsCode(renewalView.getGoodsId(), execute.body(), type);
+		String code = getDifferentGoodsCode(renewalView.getGoodsId(), execute.body(), type, sync);
 		GroupsRelationLoginCodeRecord record = new GroupsRelationLoginCodeRecord();
 		record.setUserId(userId);
 		record.setRelationId(relationId);
@@ -739,30 +758,41 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		return expiryTickets;
 	}
 
-	public String getDifferentGoodsCode(Long goodsId, String body, Integer type) {
+	public String getDifferentGoodsCode(Long goodsId, String body, Integer type, Boolean sync) {
 		String code = null;
 		//奈飞
 		if (goodsId == 1) {
-			if (body.contains("輸入此代碼登入")) {
-				code = StrUtil.subBetween(body, "輸入此代碼登入", "請在裝置上輸入上");
+			if (type != null && type == 1) {
+				if (body.contains("輸入此代碼登入") || body.contains("输入此代码登录")) {
+					code = StrUtil.subBetween(body, "輸入此代碼登入", "請在裝置上輸入上");
+					if (StrUtil.isEmpty(code)) {
+						code = StrUtil.subAfter(body, "输入此代码登录", true);
+					}
+				}
+				if (StrUtil.isEmpty(code)) {
+					throw BusinessRuntimeException.getInstance("查询失败,请检查是否发送了登陆码..");
+				}
 			} else {
 				String urlPref = "https://www.netflix.com/account/update-primary-location";
 				code = StrUtil.subBetween(body, "[" + urlPref, "]");
 				if (StrUtil.isEmpty(code)) {
 					urlPref = "https://www.netflix.com/account/travel/verify";
 					code = StrUtil.subBetween(body, "[" + urlPref, "]");
-					if (StrUtil.isEmpty(code) && type == null) {
+					if (StrUtil.isEmpty(code)) {
 						throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
 					}
 				}
-				if (StrUtil.isNotBlank(code)) {
-					return urlPref + code;
+				String url = urlPref + code;
+				//非点击装置同步更新按钮 直接返回链接
+				if (!sync) return url;
+				//失败返回验证链接
+				if (!groupsRelationNetflixService.confirmUpdate(url)) {
+					return url;
 				}
-			}
-			if (type != null && type == 1 && StrUtil.isEmpty(code)) {
-				throw BusinessRuntimeException.getInstance("查询失败,请检查是否发送了登陆码..");
+				return StrUtil.EMPTY;
 			}
 		}
+		//除奈飞
 		if (StrUtil.isEmpty(code)) {
 			code = TicketCodeCommonUtil.getTicketCodeStr(body, goodsId);
 		}
@@ -846,4 +876,47 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		}
 		return renewalView;
 	}
+
+	private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user) {
+		DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build());
+		if (distributePosterGoodsDetailView == null) {
+			return null;
+		}
+		distributePosterGoodsDetailView.setNickname(user.getNickname());
+		UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class)
+				.eq(UserDistribute::getUserId, user.getId())
+				.eq(UserDistribute::getDeleted, 1)
+				.last("limit 1"));
+		if (userDistribute != null) {
+			UserPlatDistributeRate userPlatDistributeRate = userPlatDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatDistributeRate.class)
+					.eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId())
+					.eq(UserPlatDistributeRate::getGoodsId, ticket.getGoodsId())
+					.last("limit 1"));
+			if (userPlatDistributeRate != null) {
+				distributePosterGoodsDetailView.setRate(userPlatDistributeRate.getRate());
+			}
+		}
+		GoodsDon goodsDon = goodsDonMapper.selectById(ticket.getGoodsId());
+		if (goodsDon.getIsSkuDistribute()) {
+			if (userDistribute != null) {
+				UserPlatSkuDistributeRate userPlatSkuDistributeRate = userPlatSkuDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatSkuDistributeRate.class)
+						.eq(UserPlatSkuDistributeRate::getDistributeId, userDistribute.getId())
+						.eq(UserPlatSkuDistributeRate::getSkuId, ticket.getSkuId())
+						.last("limit 1"));
+				if (userPlatSkuDistributeRate != null) {
+					distributePosterGoodsDetailView.setRate(userPlatSkuDistributeRate.getRate());
+				}
+			} else {
+				DistributeGeneralSkuRate distributeGeneralSkuRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
+						.eq(DistributeGeneralSkuRate::getSkuId, ticket.getSkuId())
+						.last("limit 1"));
+				if (distributeGeneralSkuRate != null) {
+					distributePosterGoodsDetailView.setRate(distributeGeneralSkuRate.getRate());
+				}
+			}
+		}
+		return distributePosterGoodsDetailView;
+	}
+
 }

+ 52 - 3
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java

@@ -1,5 +1,8 @@
 package com.cyksj.service.relation.impl;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
@@ -15,8 +18,10 @@ import com.cyksj.model.entity.Account;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.entity.GroupsTrips;
 import com.cyksj.model.entity.User;
+import com.cyksj.redis.RedisService;
 import com.cyksj.service.relation.GroupsRelationNetflixService;
 import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.task.JobManager;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -46,14 +51,21 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 
 	private final UserBindRelationService userBindRelationService;
 
+	private final RedisService redisService;
+
+	private final JobManager jobManager;
+
 	@Override
-	public JSONObject setNetflixSeatNum(Integer seatNum, String seatName, String account, String password, Date expiryTime) {
+	public JSONObject setNetflixSeatNum(Integer seatNum, String seatName, String account, String password, Date expiryTime, String code) {
 		JSONObject params = new JSONObject();
 		params.putOpt("username", account);
 		params.putOpt("password", password);
 		params.putOpt("seat_name", seatName);
 		params.putOpt("seat_num", seatNum);
 		params.putOpt("seat_time", expiryTime);
+		if (StrUtil.isNotBlank(code)) {
+			params.putOpt("pin_code", code);
+		}
 		//设置座位
 		String url = Constant.ZHAOJU_MOVIES + "/netflix_set/netflix_seat";
 		log.info("设置账号:{} 奈飞用户:{}座位信息", account, seatName);
@@ -82,7 +94,7 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 	}
 
 	@Override
-	public JSONObject setNetflixPin(Long relationId, long userId) {
+	public JSONObject setNetflixPin(Long relationId, long userId, String code) {
 		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
 		GroupsRelation relation = relationMapper.selectById(relationId);
 		if (!userIdList.contains(relation.getUserId())) {
@@ -94,7 +106,7 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 			throw BusinessRuntimeException.getInstance("系统错误");
 		}
 		User user = userMapper.selectById(relation.getUserId());
-		return setNetflixSeatNum(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime());
+		return setNetflixSeatNum(relation.getNum(), user.getNickname(), account.getAccount(), account.getPassword(), relation.getExpiryTime(), code);
 	}
 
 	@Override
@@ -116,4 +128,41 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 		Integer status = data.getInt("status");
 		return status;
 	}
+
+	@Override
+	public Boolean confirmUpdate(String nfUrl) {
+		JSONObject params = new JSONObject();
+		params.putOpt("url", nfUrl);
+		//确认更新点击
+		String url = Constant.ZHAOJU_MOVIES + "/netflix_set/netflix_primary_action";
+		try {
+			cn.hutool.http.HttpResponse execute = HttpUtil
+					.createPost(url)
+					.body(params.toString(), "application/json")
+					.setConnectionTimeout(30000)
+					.setReadTimeout(30000)
+					.execute();
+			JSONObject resp = Jsons.parseObject(execute.body(), JSONObject.class);
+			return resp.getBool("success");
+		} catch (Exception e) {
+		}
+		return false;
+	}
+
+	/**
+	 * 定时设置座位号
+	 * 30s执行一次
+	 */
+	@Override
+	public void timingSetNetflix(Integer num, String nickname, String account, String password, Date expiryTime) {
+		String key = RedisService.key.NETFLIX_SET_LIMIT_TIME.getName();
+		if (!redisService.setNx(key, 1L, 30L)) {
+			jobManager.addJob(30001, () -> {
+				timingSetNetflix(num, nickname, account, password, expiryTime);
+			});
+		} else {
+			setNetflixSeatNum(num, nickname, account, password, expiryTime, null);
+			log.info("当前时间:{}开始调用设置奈飞座位信息接口", DateTime.now());
+		}
+	}
 }

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/stripe/StripeService.java

@@ -4,7 +4,9 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.StripePayConfigMapper;
+import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.StripePayConfig;
 import com.cyksj.model.request.OrderRefundReq;
@@ -41,10 +43,18 @@ public class StripeService {
 
     private final StripePayConfigMapper stripePayConfigMapper;
 
+    private final GoodsDonSkuMapper skuMapper;
+
 
 
     public String checkOutStripe(Long orderId,String successUrl) throws Exception{
         OrderDon orderDon = orderDonService.getById(orderId);
+        if (orderDon.getGoodsId() == 26) {
+            GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+            if (!sku.getIsMirror()) {
+                throw BusinessRuntimeException.getInstance("订单异常..");
+            }
+        }
         BigDecimal money = orderDon.getMoney();
         orderDon.setType(OrderDon.Type.STRIPE);
         orderDonService.updateById(orderDon);

+ 59 - 3
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysCorpFollowServiceImpl.java

@@ -1,5 +1,6 @@
 package com.cyksj.service.sys.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -8,11 +9,11 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.mapper.SysCorpFollowMapper;
 import com.cyksj.mapper.SysCorpFollowRelateMapper;
+import com.cyksj.mapper.corp.CorpFollowMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.model.dto.YhServiceDto;
-import com.cyksj.model.entity.SysConfig;
-import com.cyksj.model.entity.SysCorpFollow;
-import com.cyksj.model.entity.SysCorpFollowRelate;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.request.sys.SysCorpFollowReq;
 import com.cyksj.service.sys.SysConfigChangeRecordService;
 import com.cyksj.service.sys.SysCorpFollowService;
@@ -20,7 +21,9 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
 
 /**
  * 项目名: yhlxj
@@ -37,6 +40,10 @@ public class SysCorpFollowServiceImpl extends ServiceImpl<SysCorpFollowMapper, S
 
 	private final SysConfigChangeRecordService sysConfigChangeRecordService;
 
+	private final CorpFollowMapper corpFollowMapper;
+
+	private final CmsUserMapper cmsUserMapper;
+
 	@Override
 	public void saveOrUpdateFollow(SysCorpFollowReq req) throws Exception {
 		SysCorpFollow sysCorpFollow = new SysCorpFollow();
@@ -69,6 +76,55 @@ public class SysCorpFollowServiceImpl extends ServiceImpl<SysCorpFollowMapper, S
 			//更新客服图片
 			updateCorpFollowImg(sysCorpFollowRelate, req.getName());
 		}
+		//同步企业客服key
+		syncSysCorpUserKey();
+	}
+
+	private void syncSysCorpUserKey() {
+		//客服群发key
+		SysConfig corpSendMsg = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.CORP_SERVICE_FOLLOWS_KEY).last("limit 1"));
+
+		//客服跟进续费key
+		SysConfig corpDutyServices = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.CORP_SERVICE_GROUPS_RELATION_FOLLOWS_KEY).last("limit 1"));
+
+		//获取目前可用值班客服
+		List<SysCorpFollowRelate> sysCorpFollowRelates = sysCorpFollowRelateMapper.selectList(Wrappers.lambdaQuery(SysCorpFollowRelate.class)
+				.eq(SysCorpFollowRelate::getStatus, 1)
+				.eq(SysCorpFollowRelate::getDeleted, 1));
+		List<String> followIds = sysCorpFollowRelates.stream().map(SysCorpFollowRelate::getFollowId).collect(Collectors.toList());
+		if (CollUtil.isNotEmpty(followIds)) {
+			try {
+				String followIdsStr = Jsons.toJson(followIds);
+				corpSendMsg.setSysValue(followIdsStr);
+				sysConfigMapper.updateById(corpSendMsg);
+
+				corpDutyServices.setSysValue(followIdsStr);
+				sysConfigMapper.updateById(corpDutyServices);
+			} catch (Exception e) {
+			}
+
+			//同步企业客服对应后台客服关系
+			List<CorpFollow> corpFollows = corpFollowMapper.selectList(Wrappers.lambdaQuery(CorpFollow.class)
+					.in(CorpFollow::getUserid, followIds)
+					.isNull(CorpFollow::getCmsUserId));
+			if (CollUtil.isNotEmpty(corpFollows)) {
+				Map<String, List<SysCorpFollowRelate>> map = sysCorpFollowRelates.stream().collect(Collectors.groupingBy(SysCorpFollowRelate::getFollowId));
+				corpFollows.forEach(e -> {
+					List<SysCorpFollowRelate> sysCorpFollowRelates1 = map.get(e.getUserid());
+					if (CollUtil.isNotEmpty(sysCorpFollowRelates1)) {
+						SysCorpFollow sysCorpFollow = this.getById(sysCorpFollowRelates1.get(0).getMid());
+						CmsUser cmsUser = cmsUserMapper.selectOne(Wrappers.lambdaQuery(CmsUser.class)
+								.eq(CmsUser::getNickname, sysCorpFollow.getName()));
+						if (cmsUser != null) {
+							e.setCmsUserId(cmsUser.getId());
+							corpFollowMapper.updateById(e);
+						}
+					}
+				});
+			}
+		}
 	}
 
 	@Override

+ 3 - 3
netflix-web/src/main/java/com/cyksj/web/controller/external/ExternalController.java

@@ -20,7 +20,7 @@ import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.request.ExchangeCodeReq;
 import com.cyksj.model.views.ExternalExchangeCodeView;
 import com.cyksj.service.exchange.ExchangeCodeService;
-import com.cyksj.service.mange.CmsOrderDonService;
+import com.cyksj.service.mange.MirrorUserCleatService;
 import com.cyksj.service.order.OrderCommonService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -57,7 +57,7 @@ public class ExternalController {
 
 	private final ExchangeCodeService exchangeCodeService;
 
-	private final CmsOrderDonService cmsOrderDonService;
+	private final MirrorUserCleatService mirrorUserCleatService;
 
 	/**
 	 * 知乎 特殊镜像规格 兑换码列表
@@ -117,7 +117,7 @@ public class ExternalController {
 
 				//清除gtpUser
 				if (orderDon.getOrderType() == 1) {
-					cmsOrderDonService.delMirrorUser(goodsDon.getId(), orderDon.getRelationId());
+					mirrorUserCleatService.delMirrorUser(goodsDon.getId(), orderDon.getRelationId());
 				}
 
 				//重新生成兑换码

+ 30 - 34
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -146,9 +146,7 @@ public class GoodsDonController {
                     .select(GoodsDonSku::getPrice));
             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);
@@ -171,11 +169,9 @@ public class GoodsDonController {
         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());
+	        data.setSold(getGoodsSold(data.getId(), data.getVirtualSold()));
 
-            Optional.ofNullable(data.getSkuList()).ifPresent(skuList -> {
+	        Optional.ofNullable(data.getSkuList()).ifPresent(skuList -> {
                 if (skuList.size() > 0) {
                     GoodsDonSku goodsDonSku = skuList.get(0);
                     data.setPrice(goodsDonSku.getPrice());
@@ -254,9 +250,7 @@ public class GoodsDonController {
 	    }
 	    DateTime now = DateTime.now();
 	    list.forEach(data -> {
-		    Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-				    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-		    data.setSold(sold + data.getSold());
+		    data.setSold(getGoodsSold(data.getId(), data.getSold()));
 		    data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, null));
 
 		    //设置特定价格
@@ -299,9 +293,7 @@ public class GoodsDonController {
 
 	    DateTime now = DateTime.now();
 	    list.forEach(data -> {
-		    Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-				    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-		    data.setSold(sold + data.getSold());
+		    data.setSold(getGoodsSold(data.getId(), data.getSold()));
 		    data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, null));
 
 		    //设置特定价格
@@ -371,9 +363,7 @@ public class GoodsDonController {
 				builder.orderBy(GoodsDonSkuFrontView::getSorted).asc();
 			}
 			views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, builder.build()));
-			Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-					.eq(OrderDon::getGoodsId, views.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-			views.setSold(sold + views.getSold());
+			views.setSold(getGoodsSold(views.getId(), views.getSold()));
 			List<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, MapUtils.builder().field(GoodsDonQaFrontView::getGoodsId, id).field(GoodsDonQaFrontView::getType, 1).build());
 			views.setQuestions(donQaFrontViews);
 			redisService.setNx(goodsDetailKey, views, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 60 * RandomUtil.randomInt(10));
@@ -493,9 +483,8 @@ public class GoodsDonController {
 			    data.setMonths(minPriceUserOwnsSku.getMonths());
 			    data.setDays(minPriceUserOwnsSku.getDays());
 		    }
-		    Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-				    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-		    data.setSold(data.getSold() + sold);
+			//销量
+		    data.setSold(getGoodsSold(data.getId(), data.getSold()));
 		    //设置特定价格
 		    setSpecificPrice(data, fUid, dsUserId.get());
 		    return true;
@@ -870,9 +859,7 @@ public class GoodsDonController {
 					}
 				});
 			}
-			Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-					.eq(OrderDon::getGoodsId, data.getGoodsId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-			data.setSold(sold + data.getSold());
+			data.setSold(getGoodsSold(data.getGoodsId(), data.getSold()));
 			data.setNotifyMsg(getPayMsgTime(data.getGoodsId(), now, 1, null));
 		});
 	}
@@ -926,9 +913,7 @@ public class GoodsDonController {
         }
         DateTime now = DateTime.now();
         list.forEach(data->{
-            Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-                    .eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-            data.setSold(sold + data.getSold());
+	        data.setSold(getGoodsSold(data.getId(), data.getSold()));
             data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, yhsId));
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(list);
@@ -989,9 +974,7 @@ public class GoodsDonController {
 			}
 			List<GoodsFrontListCategoryView> goodsFrontListViews = beanSearcher.searchAll(GoodsFrontListCategoryView.class, mapBuilder.build());
 			goodsFrontListViews.forEach(data -> {
-				Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-						.eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-				data.setSold(sold + data.getSold());
+				data.setSold(getGoodsSold(data.getId(), data.getSold()));;
 				data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, null));
 			});
 			redisService.setNx(categoryGoodsKey, goodsFrontListViews, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 10 * 60);
@@ -1063,9 +1046,7 @@ public class GoodsDonController {
 			builder.put("condition", condition);
 			List<YhShopGoodsFrontCategoryView> list = beanSearcher.searchAll(YhShopGoodsFrontCategoryView.class, builder.build());
 			list.forEach(data->{
-				Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-						.eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-				data.setSold(sold + data.getSold());
+				data.setSold(getGoodsSold(data.getId(), data.getSold()));
 				data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, yhsId));
 				//重新设置最低价格规格
 				YhShopGoodsSku sku = yhShopGoodsSkuMapper.selectMinPriceSkuByYhsId(yhsId, data.getId());
@@ -1219,9 +1200,7 @@ public class GoodsDonController {
 			subsidyDetail.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, subsidyDetail.getId()).build()));
 			MapBuilder builder = MapUtils.builder().field(GoodsDonSkuSubsidyDetailView::getGoodsId, subsidyDetail.getId());
 			subsidyDetail.setSkuList(beanSearcher.searchAll(GoodsDonSkuSubsidyDetailView.class, builder.build()));
-			Integer sold = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
-					.eq(OrderDon::getGoodsId, subsidyDetail.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
-			subsidyDetail.setSold(sold + subsidyDetail.getSold());
+			subsidyDetail.setSold(getGoodsSold(subsidyDetail.getId(), subsidyDetail.getSold()));
 
 			redisService.setNx(goodsDetailKey, Jsons.toJson(subsidyDetail), RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 60 * RandomUtil.randomInt(10));
 		}
@@ -1281,6 +1260,23 @@ public class GoodsDonController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 获取平台销量
+	 * @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());
+	}
+
 
 
 }

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

@@ -617,9 +617,9 @@ public class GroupRelationController {
      * 读取车票账号登录验证码
      */
     @GetMapping("/get/verifyCode/{relationId}")
-    public Result<String> getAiVerifyCode(@PathVariable Long relationId, Integer type) throws Exception {
+    public Result<String> getAiVerifyCode(@PathVariable Long relationId, Integer type, @RequestParam(defaultValue = "0") Boolean sync) throws Exception {
         long userId = StpUserUtil.getLoginIdAsLong();
-        return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(userId, relationId, type));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(userId, relationId, type, sync));
     }
 
     /**
@@ -842,9 +842,9 @@ public class GroupRelationController {
      * 设置pin码
      */
     @PutMapping("/set/pin/{relationId}")
-    public Result<String> setPin(@PathVariable Long relationId) {
+    public Result<String> setPin(@PathVariable Long relationId, String code) {
         long userId = StpUserUtil.getLoginIdAsLong();
-        JSONObject data = groupsRelationNetflixService.setNetflixPin(relationId, userId);
+        JSONObject data = groupsRelationNetflixService.setNetflixPin(relationId, userId, code);
         return GatewayResponse.SUCCESS.newBuilder().toResult(data.toString());
     }
 

+ 116 - 3
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -4,6 +4,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.EasyExcel;
@@ -37,6 +38,7 @@ import com.cyksj.model.request.*;
 import com.cyksj.model.views.*;
 import com.cyksj.service.mange.CmsOrderDonService;
 import com.cyksj.service.order.OrderDonCommentService;
+import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
@@ -106,6 +108,12 @@ public class CmsOrderController {
 
 	private final OrderDonCustomerServiceRelateMapper orderDonCustomerServiceRelateMapper;
 
+	private final MidjourneyUserConversationMapper midjourneyUserConversationMapper;
+
+	private final MidjourneyUserMapper midjourneyUserMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
 
 	@GetMapping("/get")
 	@SaCheckPermission("order:view")
@@ -242,6 +250,31 @@ public class CmsOrderController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 镜像规格使用详情
+	 */
+	@GetMapping("/get/order/mj/mirror/detail/{orderId}")
+	public Result<MidjourneyUserDetailView> getMjMirrorOrderDetail(@PathVariable Long orderId) {
+		OrderDon orderDon = orderDonMapper.selectById(orderId);
+		//续费订单
+		Date startTime = null;
+		Date expiryTime = null;
+		if (orderDon.getOrderType() == 2) {
+			GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+					.eq(GroupsRelation::getId, orderDon.getRelationId())
+					.eq(GroupsRelation::getUserId, orderDon.getUserId()).last("limit 1"));
+			if (relation == null) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult();
+			}
+			startTime = relation.getStartTime();
+			startTime = DateUtil.offsetMonth(startTime, sku.getMonths());
+			expiryTime = relation.getExpiryTime();
+		}
+		MidjourneyUserDetailView midjourneyUserDetailView = midjourneyUserConversationMapper.getMjMirrorOrderDetail(orderDon.getRelationId(), startTime, expiryTime);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyUserDetailView);
+	}
+
 	/**
 	 * 订单导出
 	 */
@@ -942,9 +975,89 @@ public class CmsOrderController {
 	 * midjourney查询订单用户账号剩余次数
 	 */
 	@GetMapping("/get/midjourney/user")
-	public Result<SearchResult<MidjourneyUserView>> getMidjourneyUser(Long userId,Long relationId) {
-		SearchResult<MidjourneyUserView> search = beanSearcher.search(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap())
-				.field(MidjourneyUserView::getUserId,userId).field(MidjourneyUserView::getRelationId,relationId).build());
+	public Result<MidjourneyUserDetailView> getMidjourneyUser(Long orderId) {
+		OrderDon orderDon = orderDonMapper.selectById(orderId);
+		//续费订单
+		Date startTime = null;
+		Date expiryTime = null;
+		if (orderDon.getOrderType() == 2) {
+			GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+					.eq(GroupsRelation::getId, orderDon.getRelationId())
+					.eq(GroupsRelation::getUserId, orderDon.getUserId()).last("limit 1"));
+			if (relation == null) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult();
+			}
+			startTime = relation.getStartTime();
+			startTime = DateUtil.offsetMonth(startTime, sku.getMonths());
+			expiryTime = relation.getExpiryTime();
+		}
+		MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+				.eq(MidjourneyUser::getRelationId, orderDon.getRelationId())
+				.last("limit 1"));
+		if (midjourneyUser == null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		MidjourneyUserDetailView midjourneyUserDetailView = midjourneyUserConversationMapper.getMjMirrorOrderDetail(orderDon.getRelationId(), startTime, expiryTime);
+		GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+		midjourneyUserDetailView.setUserId(orderDon.getUserId());
+		midjourneyUserDetailView.setExpiryTime(midjourneyUser.getExpireTime());
+		midjourneyUserDetailView.setMjFastNum(sku.getMjFastNum() - midjourneyUserDetailView.getUseFastNum());
+		if (sku.getMjRelaxNum() == null) {
+			midjourneyUserDetailView.setMjRelaxNum(null);
+		} else {
+			midjourneyUserDetailView.setMjRelaxNum(sku.getMjRelaxNum() - midjourneyUserDetailView.getUseRelaxNum());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyUserDetailView);
+	}
+
+	/**
+	 * 用户退款详情
+	 */
+	@GetMapping("/get/user/refund/detail")
+	public Result<OrderDonUserRefundDetailView> getUserRefundDetail(Long userId) {
+		if (userId == null || userId == 0) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		List<Long> userIdList = null;
+		try {
+			userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		} catch (Exception e) {
+		}
+		String userIds = null;
+		if (CollUtil.isNotEmpty(userIdList)) {
+			userIds = userIdList.toString().replaceAll("\\[", "").replaceAll("]", "");
+		}
+		MapBuilder builder = MapUtils.builder();
+		if (StrUtil.isNotBlank(userIds)) {
+			builder.put("uid", String.format(" and user_id in (%s)", userIds));
+		} else {
+			builder.put("uid", String.format(" and user_id = %s", userId));
+		}
+		OrderDonUserRefundDetailView orderDonUserRefundDetailView = beanSearcher.searchFirst(OrderDonUserRefundDetailView.class, builder.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonUserRefundDetailView);
+	}
+
+	/**
+	 *  用户订单列表
+	 */
+	@GetMapping("/get/user/orders")
+	public Result<SearchResult<OrderDonUserRefundDetailView.OrderDonDetailView>> getUserOrdersDetail(Long userId) {
+		if (userId == null || userId == 0) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		List<Long> userIdList = null;
+		try {
+			userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		} catch (Exception e) {
+		}
+		if (userIdList == null) {
+			userIdList = new ArrayList<>();
+			userIdList.add(userId);
+		}
+		SearchResult<OrderDonUserRefundDetailView.OrderDonDetailView> search = beanSearcher.search(OrderDonUserRefundDetailView.OrderDonDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(OrderDonUserRefundDetailView.OrderDonDetailView::getUserId, userIdList).op(Operator.InList)
+				.build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 }

+ 7 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java

@@ -88,7 +88,7 @@ public class CmsUserController{
     private final UserDoubleVerifyCodeChangeRecordMapper userDoubleVerifyCodeChangeRecordMapper;
 
     @GetMapping("/get")
-    public Result<SearchResult<UserView>> get(Long id, String otherPhone, Long sharedId, String userid, Long businessId, String sort, String order, Boolean isCert) {
+    public Result<SearchResult<UserView>> get(Long id, String otherPhone, Long sharedId, String userid, Long businessId, String sort, String order, Boolean isCert, Boolean isAbroad) {
         MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
         String otherSql = StrUtil.EMPTY;
         if (StrUtil.isNotBlank(otherPhone)) {
@@ -112,6 +112,12 @@ public class CmsUserController{
             }
             otherSql += "exists (select 1 from user_cert_record where user_id = u.id)";
         }
+        if (isAbroad != null) {
+            if (StrUtil.isNotBlank(otherSql)) {
+                otherSql += " and ";
+            }
+            otherSql += String.format(" %s (select 1 from phone_code pc where pc.phone = u.login_phone and cid is not null and cid != 86)", isAbroad ? "exists" : "not exists");
+        }
         if (StrUtil.isNotBlank(otherSql)) {
             builder.put("otherConditionSql", otherSql);
         }

+ 38 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -115,11 +115,13 @@ public class CmsAccountController {
 
 	private final ChatGptAccountService chatGptAccountService;
 
+	private final MidjourneyAccountMapper midjourneyAccountMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@GetMapping("/get")
 	@SaCheckPermission("account:view")
-	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths) {
+	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, Boolean isMjMirror) {
 		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
 		if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
 			mapBuilder.field(AccountView::getExpiryTime, expiryStartTime, expiryEndTime)
@@ -165,6 +167,12 @@ public class CmsAccountController {
 				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
 			}
 		}
+		if (isMjMirror != null) {
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			extra_sql += String.format(" %s (select 1 from midjourney_account ma where ma.account_id = a.id limit 1)", isMjMirror ? "EXISTS" : "NOT EXISTS");
+		}
 		if (StrUtil.isNotEmpty(extra_sql)) {
 			mapBuilder.put("extra_sql", extra_sql);
 		}
@@ -200,6 +208,11 @@ public class CmsAccountController {
 								.last("limit 1")))
 						.ifPresent(email -> accountView.setEmailPassword(email.getPassword()));
 			}
+			if (accountView.getGoodsId() == 26) {
+				Integer count = midjourneyAccountMapper.selectCount(Wrappers.lambdaQuery(MidjourneyAccount.class)
+						.eq(MidjourneyAccount::getAccountId, accountView.getId()));
+				accountView.setIsMjMirror(count > 0 ? true : false);
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
@@ -1258,4 +1271,28 @@ public class CmsAccountController {
 				.build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
+
+	/**
+	 * 禁用账号
+	 */
+	@PutMapping("/update/disable/{accountId}")
+	@Log(module = "平台管理/禁用账号", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> updateDisableAccount(@PathVariable Long accountId) {
+		Optional.ofNullable(accountService.getById(accountId))
+				.ifPresent(e -> {
+					e.setIsDisable(!e.getIsDisable());
+					accountService.updateById(e);
+				});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 账号禁用列表
+	 */
+	@GetMapping("/get/disable/acount")
+	public Result<SearchResult<AccountDisableView>> getDisableAccount() {
+		SearchResult<AccountDisableView> search = beanSearcher.search(AccountDisableView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(AccountDisableView::getIsDisable, 1).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
 }

+ 31 - 6
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java

@@ -352,6 +352,26 @@ public class DistributeController {
 				.select(GoodsDon::getId, GoodsDon::getType, GoodsDon::getTitle, GoodsDon::getRate, GoodsDon::getSecondRate)));
 	}
 
+	/**
+	 * 平台开启规格分销
+	 */
+	@GetMapping("/get/sku/rate")
+	public Result<List<GoodsDonSkuRateView>> getSkuRate() {
+		List<GoodsDonSkuRateView> goodsDonSkuRateViews = beanSearcher.searchAll(GoodsDonSkuRateView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.orderBy(GoodsDonSkuRateView::getGoodsId).asc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonSkuRateViews);
+	}
+
+	/**
+	 * 设置普通分销平台规格比例
+	 */
+	@PutMapping("/set/common/sku/rate")
+	public Result<String> setDistributeCommonSkuRate(@RequestBody List<DistributeGeneralSkuRate> skuRates) {
+		distributeService.setDistributeCommonSkuRate(skuRates);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
 	/**
 	 * 获取推广者分销订单详情
 	 */
@@ -473,9 +493,9 @@ public class DistributeController {
 			log.info("归还积分:{}至用户{}结束", distributeMoneyApply.getPoints(), userId);
 		}
 		if (DistributeMoneyApply.Status.success.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
-			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
-				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
-			}
+//			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
+//				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
+//			}
 			distributeMoneyApply.setImg(distributeApplyMoneyReq.getImg());
 		}
 		distributeMoneyApplyMapper.updateById(distributeMoneyApply);
@@ -496,9 +516,9 @@ public class DistributeController {
 		if (entity == null || entity.getVerifyStatus() != DistributeMoneyApply.Status.success) {
 			throw BusinessRuntimeException.getInstance("审核记录错误");
 		}
-		if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
-			throw BusinessRuntimeException.getInstance("打款截图为空");
-		}
+//		if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
+//			throw BusinessRuntimeException.getInstance("打款截图为空");
+//		}
 		DistributeMoneyApply apply = new DistributeMoneyApply();
 		apply.setImg(distributeApplyMoneyReq.getImg());
 		apply.setId(distributeApplyMoneyReq.getId());
@@ -787,6 +807,11 @@ public class DistributeController {
 
 		//sku规格比例设置
 		if (CollUtil.isNotEmpty(skuRates)) {
+			List<Long> collect = skuRates.stream().map(BusinessDistributeDefaultSkuRateConfig::getSkuId).collect(Collectors.toList());
+			if (CollUtil.isNotEmpty(collect)) {
+				businessDistributeDefaultSkuRateConfigMapper.delete(Wrappers.lambdaQuery(BusinessDistributeDefaultSkuRateConfig.class)
+						.notIn(BusinessDistributeDefaultSkuRateConfig::getSkuId, collect));
+			}
 			skuRates.forEach(config -> {
 				if (config.getRate() == null) {
 					config.setRate(0);

+ 114 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributePosterController.java

@@ -0,0 +1,114 @@
+package com.cyksj.web.controller.manage.distribute;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.DistributePosterGoods;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.views.DistributePosterGoodsView;
+import com.cyksj.service.distribute.DistributePosterGoodsService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributePosterController
+ * 创建者: JavaZou
+ * 创建时间:2024/6/24 15:38
+ */
+
+@RestController
+@RequestMapping("/manage/distribute/poster")
+@RequiredArgsConstructor
+public class DistributePosterController {
+	private final DistributePosterGoodsService distributePosterGoodsService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	/**
+	 * 新增海报
+	 */
+	@PostMapping("/post")
+	public Result<String> post(@RequestBody DistributePosterGoods distributePosterGoods) throws Exception {
+		distributePosterGoodsService.saveOrUpdatePo(distributePosterGoods);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除海报
+	 */
+	@DeleteMapping("/del/{id}")
+	public Result<String> del(@PathVariable Long id) {
+		distributePosterGoodsService.removeById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 编辑海报
+	 */
+	@PutMapping("/update")
+	public Result<String> update(@RequestBody DistributePosterGoods distributePosterGoods) throws Exception {
+		distributePosterGoodsService.saveOrUpdatePo(distributePosterGoods);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 海报列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<DistributePosterGoodsView>> get() {
+		SearchResult<DistributePosterGoodsView> search = beanSearcher.search(DistributePosterGoodsView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		search.getDataList().forEach(e -> {
+			if (StrUtil.isNotBlank(e.getSkuIds())) {
+				try {
+					String specVal = skuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
+									.in(GoodsDonSku::getId, Jsons.parseSet(e.getSkuIds(), Long.class)))
+							.stream().map(GoodsDonSku::getSpecVal).collect(Collectors.joining(","));
+					e.setSpecVal(specVal);
+				} catch (Exception ex) {
+				}
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 海报上下架
+	 */
+	@PutMapping("/update/status/{id}")
+	public Result<String> updateStatus(@PathVariable Long id) {
+		Optional.ofNullable(distributePosterGoodsService.getById(id))
+				.ifPresent(e -> {
+					e.setStatus(!e.getStatus());
+					distributePosterGoodsService.updateById(e);
+				});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 关联平台
+	 */
+	@GetMapping("/get/relate/goods")
+	public Result<List<DistributePosterGoodsView>> getRelateGoods() {
+		List<DistributePosterGoodsView> distributePosterGoodsViews = beanSearcher.searchAll(DistributePosterGoodsView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.onlySelect(DistributePosterGoodsView::getGoodsId, DistributePosterGoodsView::getTitle)
+				.orderBy(DistributePosterGoodsView::getGoodsId).asc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(distributePosterGoodsViews);
+	}
+}

+ 12 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java

@@ -23,6 +23,7 @@ import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.GroupsRelationBackView;
+import com.cyksj.model.views.DisableAccountView;
 import com.cyksj.model.views.GroupsRelationIndependentView;
 import com.cyksj.model.views.GroupsRelationRechargeView;
 import com.cyksj.model.views.OrderDonRenewView;
@@ -251,4 +252,15 @@ public class CmsGroupRelationController {
         groupRelationClearService.clearTicket(relation, UserTicketClearedRecord.Source.manual);
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
+
+    /**
+     * GPT PLUS 禁用账号列表
+     */
+    @GetMapping("/get/disable/account")
+    public Result<SearchResult<DisableAccountView>> getDisableAccount() {
+        SearchResult<DisableAccountView> search = beanSearcher.search(DisableAccountView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(DisableAccountView::getGoodsId, 18)
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 }

+ 23 - 4
netflix-web/src/main/java/com/cyksj/web/controller/manage/statistics/StatisticsDataController.java

@@ -14,10 +14,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.CustomerServiceRenewOrderRecordMapper;
-import com.cyksj.mapper.GroupsRelationMapper;
-import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.corp.CorpUserAuthMapper;
 import com.cyksj.mapper.manage.CustomerServiceEveryMonthDetailMapper;
 import com.cyksj.mapper.manage.RealGoodsOrderHandleMapper;
@@ -87,6 +84,10 @@ public class StatisticsDataController {
 
 	private final OrderDonMapper orderDonMapper;
 
+	private final MidjourneyUserMapper midjourneyUserMapper;
+
+	private final ChatgptUserMapper chatgptUserMapper;
+
 	/**
 	 * 查询头部统计数据
 	 */
@@ -207,6 +208,24 @@ public class StatisticsDataController {
 		incrExpiryTimeRecord.setRemark(renewTimeUpReq.getRemark());
 		relation.setExpiryTime(DateUtil.offsetDay(relation.getExpiryTime(), renewTimeUpReq.getDays()));
 		groupsRelationMapper.updateById(relation);
+
+		//扣除镜像过期时间
+		ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
+				.eq(ChatgptUser::getRelationId, relation.getId())
+				.last("limit 1"));
+		if (chatgptUser != null) {
+			chatgptUser.setExpireTime(DateUtil.offsetDay(chatgptUser.getExpireTime(), renewTimeUpReq.getDays()));
+			chatgptUserMapper.updateById(chatgptUser);
+		} else {
+			MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+					.eq(MidjourneyUser::getRelationId, relation.getId())
+					.last("limit 1"));
+			if (midjourneyUser != null) {
+				midjourneyUser.setExpireTime(DateUtil.offsetDay(midjourneyUser.getExpireTime(), renewTimeUpReq.getDays()));
+				midjourneyUserMapper.updateById(midjourneyUser);
+			}
+		}
+
 		//记录操作日志
 		incrExpiryTimeRecord.setUserId(relation.getUserId());
 		incrExpiryTimeRecord.setRelationId(relation.getId());

+ 5 - 4
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -36,6 +36,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -215,14 +216,14 @@ public class MirrorController {
      * @return
      */
     @GetMapping("/gpt/cars")
-    public Result<Set<ChatgptCarInfoView>> getCarInfoList(Long relationId,@RequestParam(defaultValue = "10") Integer limit,@RequestParam(defaultValue = "false") Boolean isPlus) {
+    public Result<List<ChatgptCarInfoView>> getCarInfoList(Long relationId,@RequestParam(defaultValue = "20") Integer limit,@RequestParam(defaultValue = "true") Boolean isPlus) {
         long userId = StpUserUtil.getLoginIdAsLong();
         //查看用户是否存在车票
         ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUser(userId, relationId);
         if (carChatGptUser == null) {
             throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
-        Set<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(),10, isPlus);
+        List<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(),limit, isPlus);
         for (ChatgptCarInfoView chatgptCarInfoView : carInfoList) {
             Double score = BigDecimal.valueOf(chatgptCarInfoView.getScore()).multiply(BigDecimal.valueOf(0.5)).setScale(0, RoundingMode.DOWN).doubleValue();
             chatgptCarInfoView.setScore(score);
@@ -308,13 +309,13 @@ public class MirrorController {
      * 根据userToken获取车队列表
      */
     @GetMapping("/gpt/cars/withToken")
-    public Result<Set<ChatgptCarInfoView>> getCarInfoListWithToken(String userToken,@RequestParam(defaultValue = "10") Integer limit, @RequestParam(defaultValue = "false") Boolean isPlus) {
+    public Result<List<ChatgptCarInfoView>> getCarInfoListWithToken(String userToken,@RequestParam(defaultValue = "10") Integer limit, @RequestParam(defaultValue = "false") Boolean isPlus) {
         //查看用户是否存在车票
         ChatgptUser carChatGptUser = chatGptAccountService.getCarChatGptUserWithToken(userToken);
         if (carChatGptUser == null) {
             throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
-        Set<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(), limit, isPlus);
+        List<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(), limit, isPlus);
         return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
     }
 

+ 12 - 12
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -38,7 +38,6 @@ import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.paypal.PayPalService;
 import com.cyksj.service.paypal.PaypalPayConfigService;
-import com.cyksj.service.shop.YhShopFrontService;
 import com.cyksj.service.stripe.StripePayConfigService;
 import com.cyksj.service.stripe.StripeService;
 import com.cyksj.service.user.UserBindRelationService;
@@ -123,9 +122,6 @@ public class OrderController {
     @Autowired
     private StripeService stripeService;
 
-    @Autowired
-    private YhShopFrontService yhShopFrontService;
-
     @Autowired
     private MidjourneyAccountService midjourneyAccountService;
 
@@ -145,9 +141,11 @@ public class OrderController {
         log.info("{}[start] params:{}", methodName, payRequest);
 
         String ip = ServletUtil.getClientIP(request);
-//        if (StringUtil.getInternalAddressByIP(ip).contains("柬埔寨")) {
-//            throw BusinessRuntimeException.getInstance("系统异常");
-//        }
+        String address = StringUtil.getNewInternalAddressByIp(ip);
+        //address.contains("柬埔寨") ||
+        if (address.contains("缅甸")) {
+            throw BusinessRuntimeException.getInstance("用户系统异常");
+        }
         payRequest.setIp(ip);
 
         OrderDon orderDon = orderDonService.submit(payRequest);
@@ -580,7 +578,7 @@ public class OrderController {
      * 是否绑定了邮箱或手机号
      */
     @GetMapping("/isBind")
-    public Result<Boolean> isBindPhoneOrEmail() {
+    public Result<Boolean> isBindPhoneOrEmail(@RequestParam(defaultValue = "1") Boolean fip) {
         Long userId = StpUserUtil.getLoginIdAsLong();
         User user = userMapper.selectById(userId);
         if (user == null) {
@@ -594,10 +592,12 @@ public class OrderController {
         UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
                 .eq(StrUtil.isNotEmpty(user.getOpenId()), UserBindDetail::getUserId, userId)
                 .eq(StrUtil.isNotEmpty(user.getEmail()), UserBindDetail::getEmailUserId, userId).last("limit 1"));
-        //台湾ip
-        String address = StringUtil.getNewInternalAddressByIp(ServletUtil.getClientIP(request));
-        if (address.contains("台湾") || !address.contains("中国")) {
-            return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+        if (fip) {
+            //台湾ip
+            String address = StringUtil.getNewInternalAddressByIp(ServletUtil.getClientIP(request));
+            if (address.contains("台湾") || !address.contains("中国")) {
+                return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+            }
         }
         if (userBindDetail == null || StrUtil.isEmpty(userBindDetail.getPhone())) {
             return GatewayResponse.SUCCESS.newBuilder().toResult(false);

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java

@@ -73,7 +73,7 @@ public class RegisterController {
         boolean isFree = false;
         //判断Spotify是否拥有免费资格
         if("spotify".equals(req.getPlatform())){
-            isFree = registerOrderDonService.isFree(userId,req.getPlatform());
+            isFree = registerOrderDonService.isFree(userId,req.getPlatform(),req.getCode());
         }
         RegisterOrderDon orderDon = registerOrderDonService.saveOrder(userId,req,isFree);
 

+ 8 - 0
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java

@@ -26,6 +26,7 @@ import com.cyksj.model.entity.SysConfig;
 import com.cyksj.model.entity.SysConfigChangeRecord;
 import com.cyksj.model.views.HelpQuestionClassificationView;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CorpCustomerAcquisitionLinkService;
 import com.cyksj.service.sys.SysConfigChangeRecordService;
 import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.web.util.StpUserUtil;
@@ -69,6 +70,8 @@ public class SysConfigController {
 
 	private final CpsUserAdRecordMapper cpsUserAdRecordMapper;
 
+	private final CorpCustomerAcquisitionLinkService corpCustomerAcquisitionLinkService;
+
 	@GetMapping("/get")
 	public Result<SysConfig> get(String key) {
 		SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, key).last(" limit 1"));
@@ -113,6 +116,11 @@ public class SysConfigController {
 
 		sysConfigService.updateById(sysConfig);
 
+		//同步获客值班客服
+		if (Constant.serviceKeys.get(0).equals(sysConfig.getSysKey())) {
+			corpCustomerAcquisitionLinkService.syncDutyLinkUrl();
+		}
+
 		if (changeRecord.getChangeCsImg()) {
 			//立即执行客服值班定时任务
 			XxlJobUtil.executeMarkDynamicRuleTagJob(XxlJobInfo.getExecuteTaskInstance(Constant.CORP_LINK_JOB_ID, StrUtil.EMPTY).toString());

+ 17 - 2
netflix-web/src/main/java/com/cyksj/web/controller/sys/SysCorpFollowController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.sys;
 
+import cn.hutool.core.collection.CollUtil;
 import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
@@ -8,6 +9,7 @@ import com.cyksj.model.request.sys.SysCorpFollowReq;
 import com.cyksj.model.views.SysCorpFollowView;
 import com.cyksj.model.views.SysCorpMasterFollowView;
 import com.cyksj.service.corp.CorpService;
+import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.sys.SysCorpFollowService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.util.MapUtils;
@@ -18,6 +20,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * 项目名: yhlxj
@@ -43,6 +46,10 @@ public class SysCorpFollowController {
 
 	private final HttpServletRequest request;
 
+	private final WxCorpOps wxCorpOps;
+
+	private final YHLXWxCorpConfig corpConfig;
+
 	/**
 	 * 新增客服
 	 */
@@ -74,12 +81,20 @@ public class SysCorpFollowController {
 	 * 客服列表
 	 */
 	@GetMapping("/get")
-	public Result<List<SysCorpFollowView>> get() {
+	public Result<List<SysCorpFollowView>> get(@RequestParam(required = false) Boolean isOpen) throws Exception {
+		List<String> res = wxCorpOps.getPermitUserList(corpConfig.getCorpId(), null);
 		List<SysCorpFollowView> sysCorpFollowViews = beanSearcher.searchAll(SysCorpFollowView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
-		sysCorpFollowViews.forEach(e->{
+		sysCorpFollowViews.forEach(e -> {
 			Integer num = corpUserFollowRelationMapper.selectNumOfCorpuserByFollowId(e.getFollowId());
 			e.setNumOfCorpUser(num);
+			//是否开启企业会话
+			if (CollUtil.isNotEmpty(res) && res.contains(e.getFollowId())) {
+				e.setIsOpen(true);
+			}
 		});
+		if (isOpen != null) {
+			sysCorpFollowViews = sysCorpFollowViews.stream().filter(e -> e.getIsOpen() == isOpen).collect(Collectors.toList());
+		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult(sysCorpFollowViews);
 	}
 

+ 105 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -8,8 +8,13 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
+import com.cyksj.mapper.manage.distribute.DistributeGeneralSkuRateMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper;
+import com.cyksj.mapper.manage.distribute.UserPlatSkuDistributeRateMapper;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
@@ -73,6 +78,16 @@ public class UserController {
 
     private final CorpInteractiveReaderFrontService corpInteractiveReaderFrontService;
 
+    private final UserPlatSkuDistributeRateMapper userPlatSkuDistributeRateMapper;
+
+    private final UserPlatDistributeRateMapper userPlatDistributeRateMapper;
+
+    private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
+
+    private final GoodsDonSkuMapper skuMapper;
+
+    private final UserDistributeMapper userDistributeMapper;
+
     @GetMapping(value = "/wx/whoami")
     public Result<UserWhoami> whoami() {
         long userId = StpUserUtil.getLoginIdAsLong();
@@ -426,4 +441,94 @@ public class UserController {
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
+    /**
+     * 推广平台海报列表
+     */
+    @GetMapping("/get/ds/poster/goods")
+    public Result<List<DistributePosterGoodsFrontView>> getPosterGoods() {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class)
+                .eq(UserDistribute::getUserId, userId)
+                .eq(UserDistribute::getDeleted, 1)
+                .last("limit 1"));
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        List<DistributePosterGoodsFrontView> searchAll = beanSearcher.searchAll(DistributePosterGoodsFrontView.class, builder.build());
+        searchAll.forEach(e -> {
+            if (userDistribute != null) {
+                UserPlatDistributeRate userPlatDistributeRate = userPlatDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatDistributeRate.class)
+                        .eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId())
+                        .eq(UserPlatDistributeRate::getGoodsId, e.getGoodsId())
+                        .last("limit 1"));
+                if (userPlatDistributeRate != null) {
+                    e.setRate(userPlatDistributeRate.getRate());
+                }
+            }
+            if (e.getIsSkuRate()) {
+                GoodsDonSku sku = skuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
+                        .eq(GoodsDonSku::getGoodsId, e.getGoodsId())
+                        .eq(GoodsDonSku::getStatus, 1)
+                        .orderByAsc(GoodsDonSku::getPrice)
+                        .last("limit 1"));
+                //先获取价格最低的规格对应的 比例
+                //渠道
+                if (userDistribute != null) {
+                    UserPlatSkuDistributeRate minPriceSkuRate = userPlatSkuDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatSkuDistributeRate.class)
+                            .eq(UserPlatSkuDistributeRate::getDistributeId, userDistribute.getId())
+                            .eq(UserPlatSkuDistributeRate::getGoodsId, e.getGoodsId())
+                            .eq(UserPlatSkuDistributeRate::getSkuId, sku.getId())
+                            .last("limit 1"));
+                    if (minPriceSkuRate != null && minPriceSkuRate.getRate() != 0) {
+                        e.setRate(minPriceSkuRate.getRate());
+                    } else {
+                        UserPlatSkuDistributeRate userPlatSkuDistributeRate = userPlatSkuDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatSkuDistributeRate.class)
+                                .eq(UserPlatSkuDistributeRate::getDistributeId, userDistribute.getId())
+                                .eq(UserPlatSkuDistributeRate::getGoodsId, e.getGoodsId())
+                                .ne(UserPlatSkuDistributeRate::getRate, 0)
+                                //上架
+                                .apply("exists (select 1 from goods_don_sku sku where sku.id = sku_id and sku.status is true limit 1)")
+                                .orderByAsc(UserPlatSkuDistributeRate::getRate)
+                                .last("limit 1"));
+                        if (userPlatSkuDistributeRate != null) {
+                            e.setRate(userPlatSkuDistributeRate.getRate());
+                            sku = skuMapper.selectById(userPlatSkuDistributeRate.getSkuId());
+                            e.setPrice(sku.getPrice());
+                        }
+                    }
+                } else {
+                    //普通
+                    DistributeGeneralSkuRate minPriceRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
+                            .eq(DistributeGeneralSkuRate::getGoodsId, e.getGoodsId())
+                            .eq(DistributeGeneralSkuRate::getSkuId, sku.getId())
+                            .last("limit 1"));
+                    if (minPriceRate != null && minPriceRate.getRate() > 0) {
+                        e.setRate(minPriceRate.getRate());
+                    } else {
+                        DistributeGeneralSkuRate distributeGeneralSkuRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
+                                .eq(DistributeGeneralSkuRate::getGoodsId, e.getGoodsId())
+                                .apply("exists (select 1 from goods_don_sku sku where sku.id = sku_id and sku.status is true limit 1)")
+                                .ne(DistributeGeneralSkuRate::getRate, 0)
+                                .orderByAsc(DistributeGeneralSkuRate::getRate)
+                                .last("limit 1"));
+                        if (distributeGeneralSkuRate != null) {
+                            e.setRate(distributeGeneralSkuRate.getRate());
+                            sku = skuMapper.selectById(distributeGeneralSkuRate.getSkuId());
+                            e.setPrice(sku.getPrice());
+                        }
+                    }
+                }
+            }
+        });
+        return GatewayResponse.SUCCESS.newBuilder().toResult(searchAll);
+    }
+
+    /**
+     * 海报详情
+     */
+    @GetMapping("/get/poster/{goodsId}")
+    public Result<DistributePosterGoodsFrontView> getPosterDetail(@PathVariable Long goodsId) {
+        DistributePosterGoodsFrontView distributePosterGoodsView = beanSearcher.searchFirst(DistributePosterGoodsFrontView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(DistributePosterGoodsFrontView::getGoodsId, goodsId)
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(distributePosterGoodsView);
+    }
 }