ソースを参照

Merge branch 'nf_midjourney_alpha' into dev

# Conflicts:
#	netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java
#	netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
#	netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java
chenbiao 2 年 前
コミット
d94a9bc4d1
97 ファイル変更3139 行追加1032 行削除
  1. 29 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/CuiQiuEmailConfigMapper.java
  3. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java
  4. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java
  5. 1 1
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  6. 19 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonRenewRecordMapper.java
  7. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserActivityRankRobotMapper.java
  8. 35 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserDistributeRankStatisticsRecordMapper.java
  9. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserDistributeReturnMoneyDetailMapper.java
  10. 4 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserTagMapper.java
  11. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/renew/RenewUpgradePackageMapper.java
  12. 1 1
      netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopGoodsSkuMapper.java
  13. 21 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GoodsDonPriceDto.java
  14. 18 0
      netflix-dao/src/main/java/com/cyksj/model/dto/OriSkuDto.java
  15. 21 0
      netflix-dao/src/main/java/com/cyksj/model/dto/RenewOriOrderSkuDto.java
  16. 25 1
      netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptUser.java
  17. 24 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CuiQiuEmailConfig.java
  18. 2 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java
  19. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  20. 31 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonRenewRecord.java
  21. 53 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RenewUpgradePackage.java
  22. 75 2
      netflix-dao/src/main/java/com/cyksj/model/entity/UserActivity.java
  23. 68 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserActivityRankRobot.java
  24. 57 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributeRankStatisticsRecord.java
  25. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributeReturnMoneyDetail.java
  26. 1 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpMsgAuditUserView.java
  27. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java
  28. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonSearchView.java
  29. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  30. 79 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/RenewUpgradeOrderDonView.java
  31. 1 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonBackView.java
  32. 0 5
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonView.java
  33. 50 0
      netflix-dao/src/main/java/com/cyksj/model/request/TicketLoginReq.java
  34. 20 0
      netflix-dao/src/main/java/com/cyksj/model/views/ActivityOrderDataView.java
  35. 5 0
      netflix-dao/src/main/java/com/cyksj/model/views/ChatGptUserView.java
  36. 26 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeUserRankPersonalView.java
  37. 58 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeUserRankView.java
  38. 53 0
      netflix-dao/src/main/java/com/cyksj/model/views/MidjouneyCarInfoView.java
  39. 3 3
      netflix-dao/src/main/java/com/cyksj/model/views/MidjourneyAccountView.java
  40. 25 0
      netflix-dao/src/main/java/com/cyksj/model/views/OrderDonBuyerView.java
  41. 27 0
      netflix-dao/src/main/java/com/cyksj/model/views/OrderDonLocationRelateView.java
  42. 67 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageFrontView.java
  43. 91 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageView.java
  44. 12 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  45. 77 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserActivityDistributeDetailView.java
  46. 48 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeRankActivityView.java
  47. 47 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeRankRewardDetailView.java
  48. 33 0
      netflix-dao/src/main/java/com/cyksj/model/views/userDistributeReturnMoneyDetail.java
  49. 20 0
      netflix-dao/src/main/resources/mapper/CorpUserTagMapper.xml
  50. 7 0
      netflix-dao/src/main/resources/mapper/GoodsDonSkuMapper.xml
  51. 13 0
      netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml
  52. 1 1
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  53. 19 0
      netflix-dao/src/main/resources/mapper/OrderDonRenewRecordMapper.xml
  54. 129 0
      netflix-dao/src/main/resources/mapper/UserDistributeRankStatisticsRecordMapper.xml
  55. 7 7
      netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java
  56. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpTagService.java
  57. 10 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpTagServiceImpl.java
  58. 14 0
      netflix-service/src/main/java/com/cyksj/service/distribute/UserDistributeReturnMoneyDetailService.java
  59. 8 1
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java
  60. 52 10
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  61. 31 0
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/UserDistributeReturnMoneyDetailServiceImpl.java
  62. 3 1
      netflix-service/src/main/java/com/cyksj/service/mail/CuiQiuMailService.java
  63. 61 20
      netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java
  64. 8 0
      netflix-service/src/main/java/com/cyksj/service/mange/MirrorUserCleatService.java
  65. 9 1
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  66. 56 5
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  67. 92 4
      netflix-service/src/main/java/com/cyksj/service/mange/impl/MirrorUserCleatServiceImpl.java
  68. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/renew/RenewUpgradePackageService.java
  69. 19 0
      netflix-service/src/main/java/com/cyksj/service/mange/renew/impl/RenewUpgradePackageServiceImpl.java
  70. 2 17
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java
  71. 6 15
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java
  72. 114 441
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java
  73. 2 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  74. 10 2
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderCommonServiceImpl.java
  75. 188 25
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  76. 4 0
      netflix-service/src/main/java/com/cyksj/service/pay/impl/TransferFuncServiceImpl.java
  77. 6 1
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  78. 100 18
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  79. 11 8
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java
  80. 3 3
      netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java
  81. 2 3
      netflix-service/src/main/java/com/cyksj/service/user/impl/BadIntentionOpServiceImpl.java
  82. 30 4
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserActivityServiceImpl.java
  83. 184 0
      netflix-web/src/main/java/com/cyksj/web/controller/distribute/DistributeRankController.java
  84. 21 0
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  85. 87 3
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  86. 37 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  87. 26 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java
  88. 20 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsGptCarController.java
  89. 78 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/active/UserActivityController.java
  90. 4 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgAuditController.java
  91. 9 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpTagController.java
  92. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
  93. 11 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java
  94. 132 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/renew/RenewUpgradePackageController.java
  95. 36 389
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java
  96. 73 23
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java
  97. 59 6
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

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

@@ -126,6 +126,9 @@ public interface Constant {
 
 	String NEW_APPID_NO_COUNTRY_SECRET = "朋友 %s 工作 %s 父母 %s";
 
+	//含生日
+	String NEW_APPID_NO_COUNTRY_SECRET_DATE = "%s 朋友 %s 工作 %s 父母 %s";
+
 	String ACCOUNT_DOUBLE_VERIFY_KEY = "account_double_verify_key";
 
 	/**
@@ -144,6 +147,11 @@ public interface Constant {
 	 */
 	Long GENERAL_POPULARIZE_COUPON_ID = 111l;
 
+	/**
+	 * 渠道专属优惠码
+	 */
+	Long DISTRIBUTE_POPULARIZE_COUPON_ID = 56l;
+
 	String CORP_SERVICE_FOLLOWS_KEY = "corp_service_follows_key";
 
 	String CORP_SERVICE_GROUPS_RELATION_FOLLOWS_KEY = "corp_service_groups_relation_follows_key";
@@ -334,4 +342,25 @@ public interface Constant {
 	 * 电影域名
 	 */
 	String ZHAOJU_MOVIES = "https://zhaoju666.com";
+
+	//英文
+	String EN_US = "en_US";
+
+	/**
+	 * MJ特殊价格规格
+	 */
+	String MJ_SPECIAL_SKU_PRICE_KEY = "mj_special_sku_price_key";
+
+	/**
+	 * 特殊价格规格ids
+	 */
+	List<Long> SPECIAL_PRICE_SKU_IDS = List.of(409l);
+
+	String month = "month";
+
+	String week = "week";
+
+	String money = "money";
+
+	String orders = "orders";
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CuiQiuEmailConfig;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuEmailConfigMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/7/22 15:31
+ */
+public interface CuiQiuEmailConfigMapper extends BaseMapper<CuiQiuEmailConfig> {
+}

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

@@ -1,6 +1,7 @@
 package com.cyksj.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.dto.OriSkuDto;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.YhShopGoodsSku;
 import org.apache.ibatis.annotations.Param;
@@ -24,4 +25,6 @@ public interface GoodsDonSkuMapper  extends BaseMapper<GoodsDonSku> {
 	List<Long> selectSingleSkuIdsByGoodsId(Long goodsId);
 
 	GoodsDonSku checkAndReturnMinPriceUserOwnsSku(@Param("goodsId") Long goodsId, @Param("dsUserId") Long dsUserId);
+
+	OriSkuDto selectRenewOriSku(Long skuId);
 }

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

@@ -74,4 +74,6 @@ public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
 	Long getExperienceTicket(@Param("userId") Long userId, @Param("skuId") Long skuId);
 
 	Long selectGoodsDonQaByGoodsId(Long goodsId);
+
+	GroupsRelation selectRelationByAccountAndNum(@Param("account") String account, @Param("password") String password, @Param("goodsId") Long goodsId, @Param("num") Integer num);
 }

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -38,7 +38,7 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 
 	ChannelStatisticsView selectChannelStatistics(@Param("first") String first, @Param("end") String end);
 
-	Integer selectCouponCodeUserNum(@Param("dsPopularizeId") Long dsPopularizeId, @Param("noOrderAllStatus") List<String> noOrderAllStatus);
+	Integer selectCouponCodeUserNum(@Param("dsPopularizeId") Long dsPopularizeId, @Param("exCode") String exCode, @Param("noOrderAllStatus") List<String> noOrderAllStatus);
 
 	ChannelPopularizeView countPopularizeOrderDetail(@Param("popularizeId") Long popularizeId, @Param("goodsId") Long goodsId, @Param("startTime") String startTime, @Param("endTime") String endTime);
 

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonRenewRecordMapper.java

@@ -0,0 +1,19 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.OrderDonRenewRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: OrderDonRenewRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/7/19 11:45
+ */
+public interface OrderDonRenewRecordMapper extends BaseMapper<OrderDonRenewRecord> {
+
+	OrderDon getOtherRenewSku(@Param("orderId") Long orderId, @Param("relationId") Long relationId, @Param("userIds") List<Long> userIds);
+}

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

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

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserDistributeRankStatisticsRecordMapper.java

@@ -0,0 +1,35 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.model.entity.UserActivityRankRobot;
+import com.cyksj.model.entity.UserDistributeRankStatisticsRecord;
+import com.cyksj.model.views.ActivityOrderDataView;
+import com.cyksj.model.views.DistributeUserRankView;
+import com.cyksj.model.views.UserDistributeRankActivityView;
+import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeRankStatisticsRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 16:37
+ */
+public interface UserDistributeRankStatisticsRecordMapper extends BaseMapper<UserDistributeRankStatisticsRecord> {
+	Page<DistributeUserRankView> selectDistributeRanks(@Param("filed") String filed, @Param("statisticsTime") String statisticsTime, @Param("page") Page<DistributeUserRankView> objectPage);
+
+	DistributeUserRankView getSelfRank( @Param("filed") String filed, @Param("userId") long userId, @Param("statisticsTime") String statisticsTime);
+
+	List<DistributeUserRankView> getPreviousWinners(@Param("filed") String filed, @Param("lastTime") String lastTime);
+
+	ActivityOrderDataView selectAcOrderDataView(Long acId);
+
+	Page<UserDistributeRankActivityView> rankPage(@Param("nickname") String nickname, @Param("userId") Long userId, @Param("date") String date, @Param("page") Page<UserDistributeRankActivityView> objects, @Param("filed") String filed, @Param("orderBy") String orderBy, @Param("sort") String sort);
+
+	UserActivityRankRobot getRobotRankInfo(@Param("robotId") Long robotId, @Param("filed") String filed, @Param("statisticsTime") String statisticsTime);
+
+	DistributeUserRankView getMoreSelfRank(@Param("rankId") Integer rankId, @Param("orders") Integer orders, @Param("money") BigDecimal money, @Param("filed") String filed, @Param("statisticsTime") String statisticsTime);
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserDistributeReturnMoneyDetail;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeReturnMoneyDetailMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/7/29 18:46
+ */
+public interface UserDistributeReturnMoneyDetailMapper extends BaseMapper<UserDistributeReturnMoneyDetail> {
+}

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserTagMapper.java

@@ -7,8 +7,10 @@ import com.cyksj.model.excel.CorpUserTagExcelData;
 import com.cyksj.model.views.CorpUserIntentionView;
 import com.cyksj.model.views.CorpUserView;
 import com.cyksj.model.views.UserIntentionPieView;
+import com.cyksj.model.views.UserOrderDetailView;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.Date;
 import java.util.List;
 
 
@@ -30,4 +32,6 @@ public interface CorpUserTagMapper extends BaseMapper<CorpUserTag> {
 	Page<CorpUserIntentionView> getCorpUserIntentionView(@Param("page") Page<CorpUserIntentionView> page, @Param("userId") Long userId, @Param("nickname") String nickname, @Param("tagIdStr") String tagId, @Param("thisDate") String date, @Param("intention") Integer intention);
 
 	List<CorpUserTag> selectIntentionUserTag(@Param("externalUserId") String externalUserId, @Param("groupName") String groupName);
+
+	UserOrderDetailView getFansUserToMonthOrdersDetai(@Param("tagIdStr") String tagIdStr, @Param("thisDate") String thisDate, @Param("st") Date st, @Param("et") Date et);
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.renew;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RenewUpgradePackage;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RenewUpgradePackageMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/7/18 16:56
+ */
+public interface RenewUpgradePackageMapper extends BaseMapper<RenewUpgradePackage> {
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopGoodsSkuMapper.java

@@ -23,7 +23,7 @@ public interface YhShopGoodsSkuMapper extends BaseMapper<YhShopGoodsSku> {
 	@Update("update yh_shop_goods_sku set status = 0 where sku_id = #{skuId} and price not between #{minPrice} and #{maxPrice}")
 	Integer setBelowPriceShopSkuDown(@Param("skuId") Long skuId, @Param("minPrice") BigDecimal minPrice, @Param("maxPrice") BigDecimal maxPrice);
 
-	@Select("select sku_id,price from yh_shop_goods_sku where yhs_id = #{yhsId} and goods_id = #{goodsId} and deleted is true and status is true order by price limit 1")
+	@Select("select sku_id,price from yh_shop_goods_sku ys where yhs_id = #{yhsId} and goods_id = #{goodsId} and deleted is true and status is true and exists(select 1 from goods_don_sku sku where sku.id = ys.sku_id and sku.status is true) order by price limit 1")
 	YhShopGoodsSku selectMinPriceSkuByYhsId(@Param("yhsId") Long yhsId, @Param("goodsId") Long goodsId);
 
 	@Select("select * from yh_shop_goods_sku where sku_id = #{skuId} and price not between #{minPrice} and #{maxPrice} and status = 1")

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GoodsDonPriceDto.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsDonPriceDto
+ * 创建者: JavaZou
+ * 创建时间:2024/7/22 10:30
+ */
+@Getter
+@Setter
+public class GoodsDonPriceDto {
+	private BigDecimal price;
+
+	private List<Long> sharedId;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/OriSkuDto.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class OriSkuDto {
+	private Long id;
+
+	private String specVal;
+
+	private Integer months;
+
+	private Integer gptLimitNum;
+
+	private Long gptLimitTime;
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/RenewOriOrderSkuDto.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RenewOriOrderSkuDto
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 15:14
+ */
+@Getter
+@Setter
+public class RenewOriOrderSkuDto {
+	private OriSkuDto oriSku;
+
+	private Date lastExpiryTime;
+
+}

+ 25 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptUser.java

@@ -3,6 +3,7 @@ package com.cyksj.model.entity;
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.cyksj.model.BaseEntity;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Data;
 
@@ -82,9 +83,32 @@ public class ChatgptUser extends BaseEntity {
      */
     private Long packageId;
 
+    /**
+     * 是否封禁
+     */
+    private Boolean isBlock;
+
     /**
      * 清洗套餐包时间
      */
     @TableField(updateStrategy = FieldStrategy.IGNORED)
     private Date clearPackageTime;
-}
+
+    /**
+     * 续费升级订单id
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Long renewOrderId;
+
+    /**
+     * 目前续费规格id
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Long renewSkuId;
+
+    /**
+     * 续费升级过期时间
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Date renewExpiryTime;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CuiQiuEmailConfig.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuEmailConfig
+ * 创建者: JavaZou
+ * 创建时间:2024/7/22 15:29
+ */
+@Getter
+@Setter
+public class CuiQiuEmailConfig {
+	/**
+	 * 域名前缀
+	 */
+	private String domainPrefix;
+
+	/**
+	 * 接受主邮件id
+	 */
+	private String mailId;
+}

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

@@ -56,6 +56,8 @@ public class MidjourneyUser extends BaseEntity{
      */
     private Integer mode;
 
+    private Boolean isCar;
+
     /**
      * 车票类型 2试用
      */

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java

@@ -72,7 +72,7 @@ public class OrderDon extends BaseEntity implements Serializable {
     private BigDecimal dpMoney;
 
     /**
-     * 主平台订单金额
+     * 主平台订单金额 用于加购订单分销
      */
     private BigDecimal oriMoney;
 

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonRenewRecord.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: OrderDonRenewRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/7/19 11:45
+ */
+@Getter
+@Setter
+public class OrderDonRenewRecord extends BaseEntity{
+	private Long orderId;
+
+	private Long oriSkuId;
+
+	private Long userId;
+
+	private Long packageId;
+
+	private BigDecimal discount;
+
+	/**
+	 * 是否过期,默认false
+	 */
+	private Boolean isValid;
+}

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RenewUpgradePackage.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.entity;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 14:54
+ */
+@Data
+public class RenewUpgradePackage extends BaseEntity{
+
+    /**
+     * 套餐名称
+     */
+    private String name;
+
+    /**
+     * 商品id
+     */
+    private Long goodsId;
+
+    /**
+     * 商品规格id
+     */
+    private Long skuId;
+
+    /**
+     * 续费升级规格
+     */
+    private String upgradeSkuIds;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 折扣
+     */
+    private BigDecimal discount;
+
+    /**
+     * true 上架 / false 下架
+     */
+    private Boolean status;
+
+    /**
+     * true 存在 / false 删除
+     */
+    private Boolean deleted;
+}

+ 75 - 2
netflix-dao/src/main/java/com/cyksj/model/entity/UserActivity.java

@@ -2,11 +2,14 @@ package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.cyksj.model.views.ActivityOrderDataView;
+import com.ejlchina.searcher.bean.DbIgnore;
 import lombok.Getter;
 import lombok.Setter;
 
 import javax.validation.constraints.NotEmpty;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 项目名: yhlxj
@@ -17,7 +20,7 @@ import java.util.Date;
  */
 @Getter
 @Setter
-public class UserActivity extends BaseEntity{
+public class UserActivity extends BaseEntity {
 	/**
 	 * 活动名称
 	 */
@@ -59,8 +62,78 @@ public class UserActivity extends BaseEntity{
 	@TableField(updateStrategy = FieldStrategy.IGNORED)
 	private String rules;
 
+	/**
+	 * 0.大学生认证
+	 * 1.个人分销排行
+	 */
+	private Integer type;
+
+	/**
+	 * 统计类型(周/月)
+	 * week,month
+	 */
+	private String statisticsType;
+
+	/**
+	 * 分销排行榜类型
+	 * 0.金额榜,1.打单榜
+	 */
+	private Integer rankType;
+
+	/**
+	 * 头奖范围
+	 * 5:前五名
+	 */
+	private Integer headRank;
+
+	/**
+	 * 奖励信息json
+	 */
+	private String rewardInfo;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private List<RewardInfo> rewardInfoList;
+
+	/**
+	 * 设置机器人
+	 */
+	@DbIgnore
+	@TableField(exist = false)
+	private List<UserActivityRankRobot> rankRobots;
+
+	/**
+	 * 活动订单书库
+	 */
+	@DbIgnore
+	@TableField(exist = false)
+	private ActivityOrderDataView orderDataView;
+
 	/**
 	 * 是否删除
 	 */
 	private Boolean deleted;
-}
+
+	@Getter
+	@Setter
+	public static class RewardInfo{
+
+		/**
+		 * 名次
+		 */
+		private Integer rank;
+
+		/**
+		 * 0.返现
+		 * 1.余额
+		 * 2.兑换码
+		 * 奖品类型
+		 */
+		private Integer type;
+
+		/**
+		 * 具体奖励
+		 */
+		private String reward;
+	}
+}

+ 68 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserActivityRankRobot.java

@@ -0,0 +1,68 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+public class UserActivityRankRobot extends BaseEntity{
+	private Long acId;
+
+	private String headimgurl;
+
+	private String nickname;
+
+	/**
+	 * 每日增单数开始
+	 */
+	private Integer addOrdersSt;
+
+	/**
+	 * 每日增单数结束
+	 */
+	private Integer addOrdersEt;
+
+	/**
+	 * 初始订单数
+	 */
+	private Integer initOrders;
+
+	/**
+	 * 每单金额开始
+	 */
+	private BigDecimal moneySt;
+
+	/**
+	 * 每单金额结束
+	 */
+	private BigDecimal moneyEt;
+
+	/**
+	 * 初始金额
+	 */
+	private BigDecimal initMoney;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Integer orders;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Integer orderRank;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private BigDecimal money;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Integer moneyRank;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Integer rankId;
+}

+ 57 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributeRankStatisticsRecord.java

@@ -0,0 +1,57 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeRankStatisticsRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 16:33
+ */
+@Getter
+@Setter
+public class UserDistributeRankStatisticsRecord extends BaseEntity{
+	/**
+	 * 排行类型
+	 * 0金额,1单数
+	 */
+	private Integer type;
+
+	/**
+	 * 分销用户
+	 */
+	private Long userId;
+
+	/**
+	 * 机器人id
+	 */
+	private Long robotId;
+
+	/**
+	 * 分销用户数
+	 */
+	private Integer userNUm;
+
+	/**
+	 * 分销订单数
+	 */
+	private Integer orders;
+
+	/**
+	 * 分销金额
+	 */
+	private BigDecimal money;
+
+	/**
+	 * 奖品明细
+	 */
+	private String reward;
+
+	/**
+	 * 统计类型
+	 */
+	private Integer statisticsType;
+}

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

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeReturnMoneyDetail
+ * 创建者: JavaZou
+ * 创建时间:2024/7/29 18:46
+ */
+@Getter
+@Setter
+public class UserDistributeReturnMoneyDetail extends BaseEntity{
+	private Long userId;
+
+	private BigDecimal money;
+
+	private String source;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpMsgAuditUserView.java

@@ -17,7 +17,7 @@ import java.util.Date;
         where = " c.id = cu.corp_user_id " +
                 "and cu.external_userid = cr.corp_user_id " +
                 "and f.userid = cr.follow_id " +
-                ":tag: :intention:",
+                ":tag: :intention: :talkTime:",
         groupBy = "c.name,cu.external_userid,c.avatar,c.type,c.gender,f.name,f.userid,cr.agree_status,cr.add_created_time"
 )
 public class CorpMsgAuditUserView {

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

@@ -287,4 +287,13 @@ public class OrderDonBackView {
 
 	@DbField("sku.mj_relax_num")
 	private Integer mjRelaxNum;
+
+	@DbIgnore
+	private Date oriPayTime;
+
+	@DbIgnore
+	private String oriSpecVal;
+
+	@DbIgnore
+	private String expiryTime;
 }

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

@@ -64,6 +64,9 @@ public class OrderDonSearchView {
 	@DbField("sku.spec_val")
 	private String specVal;
 
+	@DbField("o.order_type")
+	private Integer orderType;
+
 	@DbField("sku.months")
 	private Integer months;
 
@@ -164,4 +167,10 @@ public class OrderDonSearchView {
 
 	@DbField("sku.is_mirror")
 	private Boolean isMirror;
+
+	/**
+	 * 原先规格
+	 */
+	@DbIgnore
+	private String oriSpecVal;
 }

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

@@ -158,6 +158,12 @@ public class OrderDonView {
     @DbField("o.yhs_id")
     private Long yhsId;
 
+    @DbField("o.order_type")
+    private Integer orderType;
+
+    @DbIgnore
+    private Boolean isRenewPackage;
+
     @DbIgnore
     private OrderDonWaybill waybill;
 

+ 79 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/RenewUpgradeOrderDonView.java

@@ -0,0 +1,79 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.UpgradeOrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:56 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don_renew_record orr left join order_don o on o.id = orr.order_id" +
+        " left join goods_don g on g.id = o.goods_id" +
+        " left join goods_don_sku sku on o.sku_id = sku.id")
+public class RenewUpgradeOrderDonView {
+
+    @DbField("o.id")
+    private Long id;
+
+    @DbField("o.relation_id")
+    private Long relationId;
+
+    @DbField("o.order_no")
+    private String orderNo;
+
+    @DbField("o.transaction_id")
+    private String transactionId;
+
+    @DbField("g.title")
+    private String title;
+
+    @DbField("sku.spec_val")
+    private String specVal;
+
+    @DbField("g.id")
+    private Long goodsId;
+
+    @DbField("g.logo")
+    private String logo;
+
+
+    @DbField("o.user_id")
+    @JsonIgnore
+    private Long userId;
+
+    @DbField("o.money")
+    private BigDecimal money;
+
+    @DbField("o.refund_money")
+    @JsonIgnore
+    private BigDecimal refundMoney;
+
+    @DbField("o.balance")
+    private BigDecimal balance;
+
+    @DbField("o.refund_desc")
+    private String refundDesc;
+
+    @DbField("o.status")
+    private OrderDon.Status status;
+
+    @DbField("o.type")
+    private UpgradeOrderDon.Type type;
+
+    @DbField("o.created_time")
+    private Date createdTime;
+
+    @DbField("o.pay_time")
+    private Date payTime;
+
+}

+ 1 - 3
netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonBackView.java

@@ -1,7 +1,6 @@
 package com.cyksj.model.manage.views;
 
-import com.cyksj.model.entity.*;
-import com.cyksj.model.views.GoodsDonSkuView;
+import com.cyksj.model.entity.UpgradeOrderDon;
 import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
@@ -10,7 +9,6 @@ import lombok.Setter;
 
 import java.math.BigDecimal;
 import java.util.Date;
-import java.util.List;
 
 /*
  *项目名: netflix

+ 0 - 5
netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonView.java

@@ -1,12 +1,8 @@
 package com.cyksj.model.manage.views;
 
-import com.cyksj.model.entity.GoodsDon;
 import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.OrderDonWaybill;
 import com.cyksj.model.entity.UpgradeOrderDon;
-import com.cyksj.model.views.GoodsDonSkuView;
 import com.ejlchina.searcher.bean.DbField;
-import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Getter;
@@ -14,7 +10,6 @@ import lombok.Setter;
 
 import java.math.BigDecimal;
 import java.util.Date;
-import java.util.List;
 
 /**
  * @author chan

+ 50 - 0
netflix-dao/src/main/java/com/cyksj/model/request/TicketLoginReq.java

@@ -0,0 +1,50 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: TicketLoginReq
+ * 创建者: JavaZou
+ * 创建时间:2024/7/9 12:13
+ */
+@Getter
+@Setter
+public class TicketLoginReq {
+	@NotEmpty
+	private String account;
+
+	@NotEmpty
+	private String password;
+
+	@NotNull
+	private Integer num;
+
+	private Long goodsId;
+
+	private String lang = "zh_CN";
+
+	private Long relationId;
+
+	/**
+	 * 获取奈飞验证类型
+	 * 1.验证码 2.验证链接
+	 */
+	private Integer type;
+
+	/**
+	 * 是否是奈飞同步操作
+	 */
+	private Boolean sync;
+
+	private Long userId;
+
+	/**
+	 * 1.同步装置 ,2.验证链接
+	 */
+	private Integer linkType;
+}

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/views/ActivityOrderDataView.java

@@ -0,0 +1,20 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: ActivityOrderDataView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/26 16:59
+ */
+@Getter
+@Setter
+public class ActivityOrderDataView{
+	private Integer orders;
+
+	private BigDecimal money;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/views/ChatGptUserView.java

@@ -70,4 +70,9 @@ public class ChatGptUserView {
      * 目前套餐价格
      */
     private BigDecimal packagePrice;
+
+    /**
+     * 是否是续费升级
+     */
+    private Boolean isRenewPackage;
 }

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeUserRankPersonalView.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.views;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributeUserRankPersonalView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 17:43
+ */
+@Getter
+@Setter
+public class DistributeUserRankPersonalView {
+
+	/**
+	 * 个人排行
+	 */
+	private DistributeUserRankView self;
+
+	/**
+	 * 排行列表
+	 */
+	private Page<DistributeUserRankView> ranks;
+}

+ 58 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeUserRankView.java

@@ -0,0 +1,58 @@
+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.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: DistributeUserRankView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 17:30
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_distribute_rank_statistics_record udsr left join user u on u.id = udsr.user_id",
+		where = "udsr.is_present is true")
+public class DistributeUserRankView {
+
+	@DbIgnore
+	private Integer rankId;
+
+	@DbField("udsr.user_id")
+	private Long userId;
+
+	@DbField("concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*',RIGHT(ifnull(u.nickname,udsr.nickname),1))")
+	private String nickname;
+
+	@DbField("ifnull(u.headimgurl,udsr.headimgurl)")
+	private String headimgurl;
+
+	@DbField("udsr.orders")
+	private Integer orders = 0;
+
+	@DbField("udsr.statistics_start_time")
+	private String statisticsStartTime;
+
+	@DbField("udsr.money")
+	private BigDecimal money = BigDecimal.ZERO;
+
+	@DbField("udsr.reward_type")
+	private Integer rewardType;
+
+	@DbField("udsr.reward")
+	private String reward;
+
+	@DbIgnore
+	private Integer gapOrders;
+
+	@DbIgnore
+	private BigDecimal gapMoney;
+
+	@DbIgnore
+	private Boolean isPrize = false;
+}

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MidjouneyCarInfoView.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2024/8/7 13:46
+ */
+@Data
+@SearchBean(
+        tables = "midjourney_session mj "
+        ,where = "mj.status is true"
+)
+public class MidjouneyCarInfoView {
+
+
+    private Long id;
+
+    /**
+     * 状态
+     */
+    private Boolean status;
+
+    /**
+     * 是否为快速号
+     */
+    @DbField("mj.isPlus")
+    private Boolean isPlus;
+
+    /**
+     * 车id
+     */
+    @DbField("mj.carID")
+    private String carId;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 剩余快速时间
+     */
+    @DbField("mj.fastTime")
+    private Long fastTime;
+
+    /**
+     * 得分
+     */
+    private Double score;
+}

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

@@ -1,13 +1,10 @@
 package com.cyksj.model.views;
 
-import com.cyksj.model.entity.GroupsTrips;
 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.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -73,6 +70,9 @@ public class MidjourneyAccountView {
     @DbField("ma.remark")
     private String remark;
 
+    @DbField("a.api_secret")
+    private String apiSecret;
+
     @DbField("ma.created_time")
     private Date createdTime;
 

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

@@ -0,0 +1,25 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonBuyerView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/8 11:42
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don o",
+		where = "o.buyer_id is not null",
+distinct = true)
+public class OrderDonBuyerView {
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbField("o.buyer_id")
+	private String buyerId;
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/views/OrderDonLocationRelateView.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonLocationRelateView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/8 11:35
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,user_id from order_don :userId:) o inner join order_don_location_relate ocr on ocr.order_id = o.id",
+		groupBy = "ocr.ip")
+public class OrderDonLocationRelateView {
+	@DbField("any_value(o.user_id)")
+	private Long uid;
+
+	@DbField("ocr.ip")
+	private String ip;
+
+	@DbField("concat(max(ocr.country),max(ocr.province),max(ocr.city))")
+	private String address;
+}

+ 67 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageFrontView.java

@@ -0,0 +1,67 @@
+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.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RenewUpgradePackageFrontView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/19 15:19
+ */
+@Getter
+@Setter
+@SearchBean(tables = "renew_upgrade_package rup" +
+		" inner join goods_don g on g.id = rup.goods_id",
+		where = "g.status is true and rup.status is true and rup.deleted is true")
+public class RenewUpgradePackageFrontView {
+	@DbField("rup.id")
+	private Long packageId;
+
+	@DbField("rup.discount")
+	private BigDecimal discount;
+
+	@DbField("rup.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("rup.sku_id")
+	private Long skuId;
+
+	@DbField("rup.upgrade_sku_ids")
+	private String upgradeSkuIds;
+
+	@DbIgnore
+	private List<RenewSkuView> renewSkus;
+
+	@Getter
+	@Setter
+	@SearchBean(tables = "goods_don_sku sku", where = "status is true")
+	public static class RenewSkuView {
+		@DbField("sku.id")
+		private Long skuId;
+
+		@DbField("sku.months")
+		private Integer months;
+
+		@DbField("sku.gpt_limit_num")
+		private Integer gptLimitNum;
+
+		@DbField("sku.gpt_limit_time")
+		private Long gptLimitTime;
+
+		@DbField("sku.spec_val")
+		private String specVal;
+
+		@DbField("sku.price")
+		private BigDecimal price;
+	}
+}

+ 91 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageView.java

@@ -0,0 +1,91 @@
+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.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:20
+ */
+@Data
+@SearchBean(tables = "renew_upgrade_package up left join goods_don g on up.goods_id = g.id " +
+        " left join goods_don_sku sku on sku.id = up.sku_id"
+        , where = "up.deleted = true :sku:",
+        orderBy = "up.update_time desc")
+public class RenewUpgradePackageView {
+    @DbField("up.id")
+    private Long id;
+
+    /**
+     * 套餐名称
+     */
+    @DbField("up.name")
+    private String name;
+
+    /**
+     * 商品id
+     */
+    @DbField("up.goods_id")
+    private Long goodsId;
+
+    /**
+     * 商品名称
+     */
+    @DbField("g.title")
+    private String goodsName;
+
+    /**
+     * 商品规格id
+     */
+    @DbField("up.sku_id")
+    private Long skuId;
+
+    @DbField("sku.spec_val")
+    private String specVal;
+
+    /**
+     * 升级规格
+     */
+    @DbField("up.upgrade_sku_ids")
+    private String upgradeSkuIds;
+
+    /**
+     * 商品规格名称
+     */
+    @DbIgnore
+    private String upgradeSpecVal;
+
+
+    /**
+     * 备注
+     */
+    @DbField("up.remark")
+    private String remark;
+
+
+    @DbField("up.discount")
+    private BigDecimal discount;
+
+    /**
+     * true 上架 / false 下架
+     */
+    @DbField("up.status")
+    private Boolean status;
+
+	/**
+	 * true 存在 / false 删除
+	 */
+	@DbField("up.deleted")
+	private Boolean deleted;
+
+	@DbField("up.created_time")
+	private Date createdTime;
+
+	@DbField("up.update_time")
+	private Date updateTime;
+}

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

@@ -260,4 +260,16 @@ public class RenewalView {
 
     @DbIgnore
     private DistributePosterGoodsDetailView posterInfo;
+
+    /**
+     * 是否是续费升级
+     */
+    @DbIgnore
+    private Boolean isRenewPackage;
+
+    /**
+     * 续费升级折扣
+     */
+    @DbIgnore
+    private BigDecimal discount;
 }

+ 77 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserActivityDistributeDetailView.java

@@ -0,0 +1,77 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityDistributeDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 17:12
+ */
+@Data
+@SearchBean(tables = "user_activity ua"
+		, where = "ua.deleted = true :time:")
+public class UserActivityDistributeDetailView {
+	@DbField("ua.id")
+	private Integer id;
+
+	@DbField("ua.name")
+	private String name;
+
+	@DbField("ua.start_time")
+	private Date startTime;
+
+	@DbField("ua.end_time")
+	private Date endTime;
+
+	@DbField("ua.img")
+	private String img;
+
+	/**
+	 * 规则图片
+	 */
+	@DbField("ua.rules")
+	private String rules;
+
+	/**
+	 * 0.大学生认证
+	 * 1.个人分销排行
+	 */
+	@DbField("ua.type")
+	private Integer type;
+
+	/**
+	 * 统计类型(周/月)
+	 * week,month
+	 */
+	@DbField("ua.statistics_type")
+	private String statisticsType;
+
+	/**
+	 * 分销排行榜类型
+	 * 0.金额榜,1.打单榜
+	 * 2.both
+	 */
+	@DbField("ua.rank_type")
+	private Integer rankType;
+
+	/**
+	 * 头奖范围
+	 * 5:前五名
+	 */
+	@DbField("ua.head_rank")
+	private Integer headRank;
+
+	/**
+	 * 奖励信息json
+	 */
+	@DbField("ua.reward_info")
+	private String rewardInfo;
+
+	@DbField("ua.created_time")
+	private Date createdTime;
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeRankActivityView.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeRankActivityView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/26 17:04
+ */
+@Getter
+@Setter
+public class UserDistributeRankActivityView {
+
+	/**
+	 * 排行
+	 */
+	private Integer rankId;
+
+	private String statisticsStartTime;
+
+	private String statisticsEndTime;
+
+	private Long userId;
+
+	private String nickname;
+
+	private String headimgurl;
+
+	private Integer userNum;
+
+	private Integer orders;
+
+	private BigDecimal money;
+
+	/**
+	 * 奖励明细
+	 */
+	private String reward;
+
+	/**
+	 * 奖励类型
+	 */
+	private String rewardType;
+}

+ 47 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeRankRewardDetailView.java

@@ -0,0 +1,47 @@
+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
+ * 文件名: UserDistributeRankRewardDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/24 17:56
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "user_distribute_rank_reward_detail ud")
+public class UserDistributeRankRewardDetailView {
+	@DbField("ud.user_id")
+	private Long userId;
+
+	@DbField("ud.reward_type")
+	private Integer rewardType;
+
+	@DbField("ud.reward")
+	private String reward;
+
+	/**
+	 * 排行类型 0金额,1单数
+	 */
+	@DbField("ud.type")
+	private Integer type;
+
+	@DbField("ud.rank_id")
+	private Integer rankId;
+
+	@DbField("ud.statistics_start_time")
+	private String statisticsStartTime;
+
+	@DbField("ud.statistics_end_time")
+	private String statisticsEndTime;
+
+	@DbField("ud.created_time")
+	private Date createdTime;
+}

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/views/userDistributeReturnMoneyDetail.java

@@ -0,0 +1,33 @@
+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;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: userDistributeReturnMoneyDetail
+ * 创建者: JavaZou
+ * 创建时间:2024/7/24 17:56
+ */
+
+@Getter
+@Setter
+@SearchBean(tables = "user_distribute_return_money_detail ud")
+public class userDistributeReturnMoneyDetail {
+	@DbField("ud.user_id")
+	private Long userId;
+
+	@DbField("ud.money")
+	private BigDecimal money;
+
+	@DbField("ud.source")
+	private String source;
+
+	@DbField("ud.created_time")
+	private Date createdTime;
+}

+ 20 - 0
netflix-dao/src/main/resources/mapper/CorpUserTagMapper.xml

@@ -133,4 +133,24 @@
         where ct.group_name = #{groupName}
         and cufr.corp_user_id = #{externalUserId}
     </select>
+
+    <select id="getFansUserToMonthOrdersDetai" resultType="com.cyksj.model.views.UserOrderDetailView">
+        select count(distinct o.user_id) as numOfUser,count(1) as numOfOrder,
+        cast(sum(o.money)/100 as decimal(10,2)) as orderMoney,
+        count(if(goods_id = 15,1,NULL)) as numOfEpOrder,
+        cast(sum(if(goods_id = 15,o.money,0))/100 as decimal(10,2)) as epOrderMoney
+        from (select cu.user_id
+        from (select distinct cu.*
+        from (select DISTINCT relation_id from corp_user_tag where tag_id = #{tagIdStr}) ct
+        inner join corp_user_follow_relation cufr on cufr.id = ct.relation_id
+        inner join corp_user_auth ca on ca.external_userid = cufr.corp_user_id
+        inner join corp_user cu on cu.id = ca.corp_user_id and cu.user_id != 0
+        <if test="thisDate != null">
+            where date_format(cu.created_time,'%Y-%m-%d') = #{thisDate}
+        </if>
+        ) cu) cu
+        left join order_don o on o.user_id = cu.user_id
+        where o.status not in ('close','noPayment','refund')
+        and o.created_time between #{st} and #{et}
+    </select>
 </mapper>

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

@@ -48,4 +48,11 @@
             or JSON_CONTAINS(user_owns, '${dsUserId}')
         </if>) order by price limit 1
     </select>
+
+    <select id="selectRenewOriSku" resultType="com.cyksj.model.dto.OriSkuDto">
+        select *
+        from goods_don_sku
+        where id = #{skuId}
+        limit 1
+    </select>
 </mapper>

+ 13 - 0
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -363,4 +363,17 @@
           and qa.status is true
           and qa.deleted is true
     </select>
+
+    <select id="selectRelationByAccountAndNum" resultType="com.cyksj.model.entity.GroupsRelation">
+        select gr.id, gr.user_id, gr.num
+        from (select id
+              from account
+              where account = #{account}
+                and password = #{password}
+                and goods_id = #{goodsId} limit 1) a
+                 inner join groups_trips gt
+                            on gt.account_id = a.id
+                 inner join groups_relation gr on gr.groups_id = gt.id
+        where gr.num = #{num} and gr.expiry_time > now() limit 1
+    </select>
 </mapper>

+ 1 - 1
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -124,7 +124,7 @@
     </select>
 
     <select id="selectCouponCodeUserNum" resultType="java.lang.Integer">
-        select count(distinct user_id) from order_don where ds_popularize_id = #{dsPopularizeId}
+        select count(distinct user_id) from order_don where (ds_popularize_id = #{dsPopularizeId} or coupon_ex_code = #{exCode})
         and status not in
         <foreach collection="noOrderAllStatus" item="item" open="(" separator="," close=")">
             #{item}

+ 19 - 0
netflix-dao/src/main/resources/mapper/OrderDonRenewRecordMapper.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.OrderDonRenewRecordMapper">
+
+
+    <select id="getOtherRenewSku" resultType="com.cyksj.model.entity.OrderDon">
+        select o.* from (select order_id from order_don_renew_record where order_id != #{orderId}
+        and is_valid = 0
+        and user_id in
+        <foreach collection="userIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>) orr inner join order_don o on o.id = orr.order_id
+        and o.status not in ('close','noPayment','refund')
+        and o.order_type = 2 and o.relation_id = #{relationId}
+        inner join goods_don_sku sku on sku.id = o.sku_id
+        order by sku.months desc,sku.gpt_limit_num desc
+        limit 1
+    </select>
+</mapper>

+ 129 - 0
netflix-dao/src/main/resources/mapper/UserDistributeRankStatisticsRecordMapper.xml

@@ -0,0 +1,129 @@
+<?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.UserDistributeRankStatisticsRecordMapper">
+
+    <select id="selectDistributeRanks" resultType="com.cyksj.model.views.DistributeUserRankView">
+        select ROW_NUMBER()                             OVER (ORDER BY ${filed} desc) AS rank_id, concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*', RIGHT(ifnull(u.nickname,udsr.nickname),1)) as nickname,
+               ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+               udsr.statistics_start_time,
+               udsr.money,
+               udsr.orders,
+               udsr.reward_type,
+               udsr.reward
+        from user_distribute_rank_statistics_record udsr
+                 left join user u on u.id = udsr.user_id
+        where statistics_start_time = #{statisticsTime}
+        order by ${filed} desc
+    </select>
+
+    <select id="getSelfRank" resultType="com.cyksj.model.views.DistributeUserRankView">
+        select *
+        from (select ROW_NUMBER()                             OVER (ORDER BY ${filed} desc) AS rank_id, concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*', RIGHT(ifnull(u.nickname,udsr.nickname),1)) as nickname,
+                     ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+                     udsr.user_id,
+                     udsr.statistics_start_time,
+                     udsr.money,
+                     udsr.orders,
+                     udsr.reward_type,
+                     udsr.reward
+              from user_distribute_rank_statistics_record udsr
+                       left join user u on u.id = udsr.user_id
+              where statistics_start_time = #{statisticsTime}) s
+        where s.user_id = #{userId}
+    </select>
+
+    <select id="getPreviousWinners" resultType="com.cyksj.model.views.DistributeUserRankView">
+        select ROW_NUMBER()                             OVER (ORDER BY ${filed} desc) AS rank_id, concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*', RIGHT(ifnull(u.nickname,udsr.nickname),1)) as nickname,
+               ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+               udsr.user_id,
+               udsr.statistics_start_time,
+               udsr.money,
+               udsr.orders,
+               udsr.reward,
+               udsr.reward_type
+        from user_distribute_rank_statistics_record udsr
+                 left join user u on u.id = udsr.user_id
+        where statistics_start_time = #{lastTime}
+        limit 10
+    </select>
+
+    <select id="selectAcOrderDataView" resultType="com.cyksj.model.views.ActivityOrderDataView">
+        select sum(orders) as orders, sum(money) as money
+        from user_distribute_rank_statistics_record
+        where robot_id is null
+    </select>
+
+    <select id="rankPage" resultType="com.cyksj.model.views.UserDistributeRankActivityView">
+        select * from (select ROW_NUMBER() OVER (ORDER BY ${filed} desc) AS rank_id,
+        ifnull(u.nickname,udsr.nickname) as nickname,
+        ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+        udsr.user_id,
+        udsr.statistics_start_time,
+        udsr.statistics_end_time,
+        udsr.money,
+        udsr.orders,
+        udsr.reward_type,
+        udsr.reward,
+        (select count(1) from user_distribute_shared us where us.shared_id = udsr.user_id) as userNum
+        from user_distribute_rank_statistics_record udsr
+        left join user u on u.id = udsr.user_id
+        <where>
+            <if test="date != null">
+                statistics_start_time = #{date}
+            </if>
+            <if test="userId != null">
+                and udsr.user_id = #{userId}
+            </if>
+            <if test="nickname != null">
+                and u.nickname like '%${nickname}%'
+            </if>
+        </where>
+        order by ${filed} desc limit 20)
+        s
+        <if test="orderBy!=null">
+            order by ${orderBy} ${sort}
+        </if>
+    </select>
+
+    <select id="getRobotRankInfo" resultType="com.cyksj.model.entity.UserActivityRankRobot">
+        select *
+        from (select ROW_NUMBER()                             OVER (ORDER BY ${filed} desc) AS rank_id, concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*', RIGHT(ifnull(u.nickname,udsr.nickname),1)) as nickname,
+                     ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+                     udsr.user_id,
+                     udsr.statistics_start_time,
+                     udsr.money,
+                     udsr.orders,
+                     robot_id
+              from user_distribute_rank_statistics_record udsr
+                       left join user u on u.id = udsr.user_id
+              where statistics_start_time = #{statisticsTime}) s
+        where s.robot_id = #{robotId}
+    </select>
+
+    <select id="getMoreSelfRank" resultType="com.cyksj.model.views.DistributeUserRankView">
+        select *
+        from (select ROW_NUMBER() OVER (ORDER BY ${filed} desc) AS rank_id,
+        concat(LEFT(ifnull(u.nickname,udsr.nickname),1),'*', RIGHT(ifnull(u.nickname,udsr.nickname),1)) as nickname,
+        ifnull(u.headimgurl, udsr.headimgurl) as headimgurl,
+        udsr.user_id,
+        udsr.statistics_start_time,
+        udsr.money,
+        udsr.orders
+        from user_distribute_rank_statistics_record udsr
+        left join user u on u.id = udsr.user_id
+        where statistics_start_time = #{statisticsTime}) s
+        <where>
+            <if test="rankId != null">
+                s.rank_id &lt; #{rankId}
+            </if>
+            <if test="filed = 'orders'">
+                and s.orders > #{orders}
+            </if>
+            <if test="filed = 'money'">
+                and s.money > #{money}
+            </if>
+        </where>
+        order by rank_id desc limit 1
+    </select>
+</mapper>

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

@@ -16,14 +16,12 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
-import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.station.CollegeStudentStationUseTicketRecordMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.gpt.ConversationRequest;
 import com.cyksj.model.response.ConversationLimitResponse;
-import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
 import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
 import com.cyksj.redis.RedisService;
@@ -31,7 +29,6 @@ import com.cyksj.service.chatgpt.ChatGptAccountService;
 import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.ejlchina.searcher.BeanSearcher;
-import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -71,6 +68,8 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
 
     private static final long WINDOW_SIZE = 3 * 60 * 60; // 3小时窗口的秒数
 
+    private static final List<String> LOW_GPT_MODEL = List.of("gpt-4o-mini","text-davinci-002-render-sha");
+
     private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
     private final RedisService redisService;
@@ -170,7 +169,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
      * @throws Exception
      */
     private JSONObject getLoginResult(Account account) throws Exception {
-        HttpRequest request = new HttpRequest(GPT_PROXY + "/getsession");
+        HttpRequest request = new HttpRequest(GPT_PROXY + "/applelogin");
         request.form("username", account.getAccount());
         request.form("password", account.getPassword());
         request.header("Content-Type", "application/x-www-form-urlencoded");
@@ -495,7 +494,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
         chatgptUserConversationRecord.setModel(conversationRequest.getModel());
         chatgptUserConversationRecordMapper.insert(chatgptUserConversationRecord);
 
-        if(!"text-davinci-002-render-sha".equals(conversationRequest.getModel())){
+        if(!LOW_GPT_MODEL.contains(conversationRequest.getModel())){
             String key = RedisService.key.CHATGPT_CONVERSATION_LIMIT.getName() + ":" + userToken;
             long currentTimeMillis = System.currentTimeMillis();
 
@@ -514,7 +513,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
         }
 
         if (StringUtils.isNotBlank(chatgptSession.getCarId())) {
-            updateExperienceAndScore(chatgptSession.getCarId(), !"text-davinci-002-render-sha".equals(conversationRequest.getModel()), System.currentTimeMillis());
+            updateExperienceAndScore(chatgptSession.getCarId(), !LOW_GPT_MODEL.contains(conversationRequest.getModel()), System.currentTimeMillis());
         }
 
     }
@@ -524,7 +523,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
     public ConversationLimitResponse conversationLimit(String userToken, String model, String carId, ChatgptUser chatgptUser, Boolean isCar) {
         ConversationLimitResponse conversationLimitResponse = new ConversationLimitResponse();
         conversationLimitResponse.setLimited(false);
-        if (!"text-davinci-002-render-sha".equals(model)) {
+        if (!LOW_GPT_MODEL.contains(model)) {
             //如果不为车队 直接返回
             if (chatgptUser.getIsCar()) {
                 conversationLimitResponse = isConversationAllowed(userToken, chatgptUser.getLimitNum(), chatgptUser.getLimitTime());
@@ -848,6 +847,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
                     .use(Math.min(chatgptUser.getLimitNum(), getConversationCount(chatgptUser.getUserToken(), chatgptUser.getLimitTime())))
                     .packageId(chatgptUser.getPackageId())
                     .packagePrice(packagePrice)
+                    .isRenewPackage(chatgptUser.getRenewOrderId() != null ? true : false)
                     .build();
         } else {
             throw BusinessRuntimeException.getInstance("您还未购买该车票");

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpTagService.java

@@ -52,4 +52,6 @@ public interface CorpTagService {
 	Page<UserOrderDetailView> getTagUserPastRecord(Integer start, Integer limit, String tagIdStr, String startTime, String endTime, String consumeStTime, String consumeEtTime);
 
 	UserOrderDetailView tagUserHeadData(String tagIdStr, String startTime, String endTime, String consumeStTime, String consumeEtTime);
+
+	UserOrderDetailView getFansUserToMonthOrdersDetail(String tagId, String date);
 }

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpTagServiceImpl.java

@@ -1,6 +1,8 @@
 package com.cyksj.service.corp.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -460,4 +462,12 @@ public class CorpTagServiceImpl implements CorpTagService {
 		headView.setOrderRate(headView.getNumOfUser() == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(headView.getNumOfEpOrder()).divide(BigDecimal.valueOf(headView.getNumOfUser()), 2, RoundingMode.HALF_DOWN));
 		return headView;
 	}
+
+	@Override
+	public UserOrderDetailView getFansUserToMonthOrdersDetail(String tagId, String date) {
+		DateTime monthBegin = DateUtil.beginOfMonth(DateTime.now());
+		DateTime nextMonth = DateUtil.offsetMonth(monthBegin, 1);
+		UserOrderDetailView detailView = corpUserTagMapper.getFansUserToMonthOrdersDetai(tagId, date, monthBegin, nextMonth);
+		return detailView;
+	}
 }

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

@@ -0,0 +1,14 @@
+package com.cyksj.service.distribute;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeReturnMoneyDetailService
+ * 创建者: JavaZou
+ * 创建时间:2024/7/29 18:52
+ */
+public interface UserDistributeReturnMoneyDetailService {
+
+	void recordDistributeReturnMoney(Long userId, BigDecimal money, String source);
+}

+ 8 - 1
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java

@@ -10,6 +10,7 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.manage.distribute.equipment.*;
 import com.cyksj.model.dto.EquipmentConfigDto;
 import com.cyksj.model.entity.*;
@@ -68,9 +69,15 @@ public class EquipmentDistributeServiceImpl implements EquipmentDistributeServic
 
 	private final EquipmentUserPayRecordMapper equipmentUserPayRecordMapper;
 
+	private final UserMapper userMapper;
+
 	@Override
 	public void saveDistributionInvitation(Long sharedId, Boolean isNewUser, Long userId) {
-		if (sharedId.equals(userId)) {
+		if (sharedId == 0l || sharedId.equals(userId)) {
+			return;
+		}
+		User user = userMapper.selectById(sharedId);
+		if (user == null) {
 			return;
 		}
 		//邀请人是否购买了实物

+ 52 - 10
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -3,6 +3,7 @@ package com.cyksj.service.distribute.impl;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
@@ -11,6 +12,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.UserDistributeSharedRelateUnbindMapper;
+import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.manage.coupon.CouponDistributePopularizeMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.mapper.manage.distribute.*;
@@ -84,11 +86,13 @@ public class DistributeServiceImpl implements DistributeService {
 
 	private final DistributeGeneralSkuRateMapper generalSkuRateMapper;
 
+	private final UserMapper userMapper;
+
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void insertDistribute(UserDistributeReq userDistributeReq) {
-		if (!redisService.setNx(RedisService.key.USER_DISTRIBUTE_ADD_KEY.getNameFormat(userDistributeReq.getUserId()), userDistributeReq.getUserId(), 2 * 60l)) {
-			throw BusinessRuntimeException.getInstance("请勿重复点击");
+		if (!redisService.setNx(RedisService.key.USER_DISTRIBUTE_ADD_KEY.getNameFormat(userDistributeReq.getUserId()), userDistributeReq.getUserId(), 2 * 5l)) {
+			return;
 		}
 		UserDistribute exists = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeReq.getUserId()).eq(UserDistribute::getDeleted, true).last("limit 1"));
 		if (exists != null) {
@@ -155,6 +159,8 @@ public class DistributeServiceImpl implements DistributeService {
 		}
 		//渠道附加功能
 		handlerDistributeOtherFunc(userDistribute, userDistributeReq);
+		//设置过个人专属推广码 升级为渠道专属优惠码
+		setDistributePopularizeCode(userDistribute.getId(), userDistribute.getUserId());
 	}
 
 	@Override
@@ -290,7 +296,7 @@ public class DistributeServiceImpl implements DistributeService {
 	 */
 	public void handlerDistributeOtherFunc(UserDistribute userDistribute, UserDistributeReq userDistributeReq) {
 		//处理优惠券关联
-		handlerDistributeCouponRelate(userDistribute.getId(), userDistributeReq.getCouponRelates());
+		handlerDistributeCouponRelate(userDistribute.getId(), userDistribute.getUserId(), userDistributeReq.getCouponRelates());
 
 		//渠道目标额配置
 		handlerDistributeTargetAlert(userDistribute.getId(), userDistributeReq.getTargets());
@@ -304,6 +310,13 @@ public class DistributeServiceImpl implements DistributeService {
 
 	@Override
 	public void saveDistributionInvitation(Long sharedId, Long userId, Long dsPopularizeId) {
+		if (sharedId == 0l || sharedId.equals(userId)) {
+			return;
+		}
+		User user = userMapper.selectById(sharedId);
+		if (user == null) {
+			return;
+		}
 		UserDistributeShared userDistributeShared = new UserDistributeShared();
 		userDistributeShared.setSharedId(sharedId);
 		//存在分销
@@ -416,7 +429,7 @@ public class DistributeServiceImpl implements DistributeService {
 		});
 	}
 
-	private void handlerDistributeCouponRelate(Long distributeId, List<CouponDistributePopularize> couponRelates) {
+	private void handlerDistributeCouponRelate(Long distributeId, Long userId, List<CouponDistributePopularize> couponRelates) {
 		Map<Long, CouponDistributePopularize> map = new ConcurrentHashMap<>();
 		couponRelates.forEach(data -> {
 			data.setDistributeId(distributeId);
@@ -425,21 +438,29 @@ public class DistributeServiceImpl implements DistributeService {
 			}
 			Integer exists = couponMapper.selectCount(Wrappers.lambdaQuery(Coupon.class).eq(Coupon::getId, data.getCouponId()).eq(Coupon::getDeleted, 1));
 			if (exists == 0) {
-				throw BusinessRuntimeException.getInstance("id为{}的优惠券不存在", data.getCouponId());
+				throw BusinessRuntimeException.getInstance("id为{0}的优惠券不存在", data.getCouponId());
 			}
 			String exCode = data.getExCode();
 			if (StrUtil.isEmpty(exCode)) {
 				throw BusinessRuntimeException.getInstance("优惠码为空");
 			}
-			Integer count = couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class).ne(data.getId() != null, CouponDistributePopularize::getId, data.getId())
+			List<CouponDistributePopularize> popularizeList = couponDistributePopularizeMapper.selectList(Wrappers.lambdaQuery(CouponDistributePopularize.class)
 					.eq(CouponDistributePopularize::getDeleted, 1)
-					.eq(CouponDistributePopularize::getIsGeneral, false)
 					.eq(CouponDistributePopularize::getExCode, exCode));
-			if (count == 0) {
-				count = couponMapper.selectCount(Wrappers.lambdaQuery(Coupon.class).eq(Coupon::getExCode, exCode).eq(Coupon::getDeleted, true));
+			//个人渠道
+			for (CouponDistributePopularize couponDistributePopularize : popularizeList) {
+				Long disId = couponDistributePopularize.getDistributeId();
+				if (disId != null && !ObjectUtil.equal(disId, distributeId)) {
+					throw BusinessRuntimeException.getInstance("优惠码:{0}已存在", exCode);
+				}
+				Long uid = couponDistributePopularize.getUserId();
+				if (uid != null && !ObjectUtil.equal(uid, userId)) {
+					throw BusinessRuntimeException.getInstance("优惠码:{0}已存在", exCode);
+				}
 			}
+			Integer count = couponMapper.selectCount(Wrappers.lambdaQuery(Coupon.class).eq(Coupon::getExCode, exCode).eq(Coupon::getDeleted, true));
 			if (count > 0) {
-				throw BusinessRuntimeException.getInstance("优惠码:{}已存在", exCode);
+				throw BusinessRuntimeException.getInstance("优惠码:{0}已存在", exCode);
 			}
 			if (data.getId() != null) {
 				couponDistributePopularizeMapper.updateById(data);
@@ -605,4 +626,25 @@ public class DistributeServiceImpl implements DistributeService {
 			}
 		}
 	}
+
+	private void setDistributePopularizeCode(Long distributeId, Long userId) {
+		CouponDistributePopularize couponDistributePopularize = couponDistributePopularizeMapper.selectOne(Wrappers.lambdaQuery(CouponDistributePopularize.class)
+				.eq(CouponDistributePopularize::getCouponId, Constant.GENERAL_POPULARIZE_COUPON_ID)
+				.eq(CouponDistributePopularize::getUserId, userId)
+				.eq(CouponDistributePopularize::getDeleted, 1)
+				.eq(CouponDistributePopularize::getIsGeneral, 1)
+				.last("limit 1"));
+		if (couponDistributePopularize != null) {
+			//先删除
+			couponDistributePopularize.setDeleted(false);
+			couponDistributePopularizeMapper.updateById(couponDistributePopularize);
+
+			//后升级
+			CouponDistributePopularize newPopularizeCode = new CouponDistributePopularize();
+			newPopularizeCode.setDistributeId(distributeId);
+			newPopularizeCode.setExCode(couponDistributePopularize.getExCode());
+			newPopularizeCode.setCouponId(Constant.DISTRIBUTE_POPULARIZE_COUPON_ID);
+			couponDistributePopularizeMapper.insert(newPopularizeCode);
+		}
+	}
 }

+ 31 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/impl/UserDistributeReturnMoneyDetailServiceImpl.java

@@ -0,0 +1,31 @@
+package com.cyksj.service.distribute.impl;
+
+import com.cyksj.mapper.UserDistributeReturnMoneyDetailMapper;
+import com.cyksj.model.entity.UserDistributeReturnMoneyDetail;
+import com.cyksj.service.distribute.UserDistributeReturnMoneyDetailService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserDistributeReturnMoneyDetailServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/7/29 18:52
+ */
+@Service
+@RequiredArgsConstructor
+public class UserDistributeReturnMoneyDetailServiceImpl implements UserDistributeReturnMoneyDetailService {
+	private final UserDistributeReturnMoneyDetailMapper userDistributeReturnMoneyDetailMapper;
+
+
+	@Override
+	public void recordDistributeReturnMoney(Long userId, BigDecimal money, String source) {
+		UserDistributeReturnMoneyDetail userDistributeReturnMoneyDetail = new UserDistributeReturnMoneyDetail();
+		userDistributeReturnMoneyDetail.setUserId(userId);
+		userDistributeReturnMoneyDetail.setMoney(money);
+		userDistributeReturnMoneyDetail.setSource(source);
+		userDistributeReturnMoneyDetailMapper.insert(userDistributeReturnMoneyDetail);
+	}
+}

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

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

+ 61 - 20
netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java

@@ -11,15 +11,18 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.common.util.TicketCodeCommonUtil;
+import com.cyksj.mapper.CuiQiuEmailConfigMapper;
 import com.cyksj.model.dto.CuiQiuEmailDetailDto;
 import com.cyksj.model.dto.CuiQiuEmailDto;
 import com.cyksj.model.dto.CuiQiuEmailResultDto;
+import com.cyksj.model.entity.CuiQiuEmailConfig;
 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;
 
+import javax.annotation.PostConstruct;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -42,9 +45,6 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 	//脆球域名id
 	private final static String DOMAIN_ID = "1696913058045050661";
 
-	//代收管理员邮件id
-	private final static String ADMIN_MAIL_ID = "1696913058063659217";
-
 	//PS 验证码官方
 	private final static String PS_ADOBE = "Adobe";
 
@@ -52,8 +52,17 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 
 	private final static String NETFLIX = "Netflix";
 
+	private static List<CuiQiuEmailConfig> CuiQiuEmailConfigs;
+
+	private final CuiQiuEmailConfigMapper CuiQiuEmailConfigMapper;
+
+	@PostConstruct
+	public void getCuiQiuEmailConfig() {
+		CuiQiuEmailConfigs = CuiQiuEmailConfigMapper.selectList(null);
+	}
+
 	@Override
-	public String getVerifyCode(String email, Long goodsId, Integer type, Boolean sync) throws Exception {
+	public String getVerifyCode(String email, Long goodsId, Integer type, Boolean sync, Integer linkType) throws Exception {
 		//获取近二十封邮件
 		String url = "https://domain-open-api.cuiqiu.com/v1/message/list";
 
@@ -63,7 +72,11 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		//维度是天
 		DateTime now = DateTime.now();
 		params.put("token", CUI_QIU_TOKEN);
-		params.put("mail_id", ADMIN_MAIL_ID);
+		String mailId = getAdmainMailId(email);
+		if (StrUtil.isEmpty(mailId)) {
+			throw BusinessRuntimeException.getInstance("系统异常,请联系客服..");
+		}
+		params.put("mail_id", mailId);
 		params.put("start_time", DateUtil.offsetDay(now, -1).toDateStr());
 		params.put("end_time", DateUtil.offsetDay(now, 1).toDateStr());
 		params.put("to", email);
@@ -98,10 +111,10 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		}).collect(Collectors.toList());
 
 		if (CollUtil.isNotEmpty(list)) {
-			for (CuiQiuEmailDto cuiQiuEmailDto : list) {
-				Long messageId = cuiQiuEmailDto.getId();
+			for (CuiQiuEmailDto CuiQiuEmailDto : list) {
+				Long messageId = CuiQiuEmailDto.getId();
 				try {
-					String code = getVerifyCodeByEmail(messageId, goodsId, type, sync);
+					String code = getVerifyCodeByEmail(messageId, goodsId, type, sync, linkType, mailId);
 					if (StrUtil.isNotBlank(code)) {
 						return code;
 					}
@@ -112,41 +125,57 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		return null;
 	}
 
-	public String getVerifyCodeByEmail(Long messageId, Long goodsId, Integer type, Boolean sync) throws Exception {
+	@Override
+	public boolean isCuiQiuEmail(String account) {
+		for (CuiQiuEmailConfig CuiQiuEmailConfig : CuiQiuEmailConfigs) {
+			if (account.contains(CuiQiuEmailConfig.getDomainPrefix())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public String getVerifyCodeByEmail(Long messageId, Long goodsId, Integer type, Boolean sync, Integer linkType, String mailId) 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);
-		params.put("mail_id", ADMIN_MAIL_ID);
+		params.put("mail_id", mailId);
 		params.put("message_id", messageId);
 		HttpRequest post = HttpUtil.createPost(url);
 		post.form(params);
 		HttpResponse execute = post.execute();
 		String respBody = execute.body();
-		CuiQiuEmailDetailDto cuiQiuEmailDetailDto = Jsons.parseObject(respBody, CuiQiuEmailDetailDto.class);
-		CuiQiuEmailDetailDto.Content content = cuiQiuEmailDetailDto.getData().getContent();
+		CuiQiuEmailDetailDto CuiQiuEmailDetailDto = Jsons.parseObject(respBody, CuiQiuEmailDetailDto.class);
+		CuiQiuEmailDetailDto.Content content = CuiQiuEmailDetailDto.getData().getContent();
 		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("输入此代码登录")) {
+				if (body.contains("輸入此代碼登入") || body.contains("输入此代码登录") || body.contains("Enter this code to sign in")) {
 					code = StrUtil.subAfter(body, pre, false);
+					if (StrUtil.isEmpty(code)) {
+						code = StrUtil.subAfter(body, "Enter this code to sign in", true);
+					}
 				}
 				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)) {
+				String urlPref;
+				String nfVerifyUrl;
+				if (linkType == 1) {
+					urlPref = "https://www.netflix.com/account/update-primary-location";
+					nfVerifyUrl = TicketCodeCommonUtil.extractUrl(body, urlPref);
+				} else {
 					urlPref = "https://www.netflix.com/account/travel/verify";
 					nfVerifyUrl = TicketCodeCommonUtil.extractUrl(body, urlPref);
-					if (StrUtil.isEmpty(nfVerifyUrl)) {
-						throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
-					}
+				}
+				if (StrUtil.isEmpty(nfVerifyUrl)) {
+					throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
 				}
 				//非点击装置同步更新按钮 直接返回链接
-				if (!sync) return nfVerifyUrl;
+				if (linkType == 2) return nfVerifyUrl;
 				//失败返回验证链接
 				if (!groupsRelationNetflix.confirmUpdate(nfVerifyUrl)) {
 					return nfVerifyUrl;
@@ -163,4 +192,16 @@ public class CuiQiuMailServiceImpl implements CuiQiuMailService {
 		}
 		return StringUtil.getVerifyCodePattern(code, length);
 	}
+
+	/**
+	 * 获取接受邮件邮箱id
+	 */
+	private String getAdmainMailId(String email) {
+		for (CuiQiuEmailConfig CuiQiuEmailConfig : CuiQiuEmailConfigs) {
+			if (email.contains(CuiQiuEmailConfig.getDomainPrefix())) {
+				return CuiQiuEmailConfig.getMailId();
+			}
+		}
+		return null;
+	}
 }

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

@@ -1,5 +1,7 @@
 package com.cyksj.service.mange;
 
+import com.cyksj.model.entity.OrderDon;
+
 /**
  * 项目名: yhlxj
  * 文件名: MirrorUserCleatService
@@ -8,4 +10,10 @@ package com.cyksj.service.mange;
  */
 public interface MirrorUserCleatService {
 	void delMirrorUser(Long goodsId, Long relationId);
+
+	/**
+	 * 处理续费升级订单,将镜像车票还原
+	 * @param orderDon
+	 */
+	void handleRenewUpgradeOrders(OrderDon orderDon);
 }

+ 9 - 1
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -366,7 +366,15 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 								}
 								insert.setSecret(string);
 							} else {
-								insert.setSecret(Constant.AMERICA_APPID_SECRET);
+								//密保
+								if (part.length > 5) {
+									String friends = part[2];
+									String works = part[3];
+									String parents = part[4];
+									String birthday = part[5];
+									String secret = String.format(Constant.NEW_APPID_NO_COUNTRY_SECRET_DATE, birthday, friends, works, parents);
+									insert.setSecret(secret);
+								}
 							}
 						}
 					}

+ 56 - 5
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alipay.api.AlipayClient;
 import com.alipay.api.domain.AlipayTradeRefundModel;
@@ -196,6 +197,8 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final MirrorUserCleatService mirrorUserCleatService;
 
+    private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -371,6 +374,10 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         //修改订单状态
         orderDon.setStatus(OrderDon.Status.refund);
         orderDonMapper.updateById(orderDon);
+        //续费升级订单
+        if (orderDon.getOrderType() == 2 && sku.getIsMirror()) {
+            mirrorUserCleatService.handleRenewUpgradeOrders(orderDon);
+        }
         //提交过工单的订单
         //将用户异常订单关闭
         workOrderMapper.update(null, Wrappers.lambdaUpdate(WorkOrder.class)
@@ -461,9 +468,29 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                         .lt(UpgradeOrderDon::getNum, orderDon.getNum())
                         .eq(UpgradeOrderDon::getStatus, UpgradeOrderDon.Status.complete)
                         .last("limit 1"));
+                Long renewSkuId = chatgptUser.getRenewSkuId();
+
+                //续费升级
+                GoodsDonSku renewSku = null;
+                if (renewSkuId != null) {
+                    renewSku = goodsDonSkuMapper.selectById(renewSkuId);
+                    gptLimitTime = renewSku.getGptLimitTime();
+                    gptLimitNum = renewSku.getGptLimitNum();
+                }
+
                 if (secondUpgrade != null) {
                     gptLimitTime = secondUpgrade.getTime();
                     gptLimitNum = secondUpgrade.getNum();
+
+                    if (renewSku != null) {
+                        //低级套餐
+                        GoodsDonSku secondSkuUpGrade = goodsDonSkuMapper.selectById(secondUpgrade.getSkuId());
+                        //续费升级套餐更高
+                        if (renewSku.getMonths() >= secondSkuUpGrade.getMonths() && renewSku.getGptLimitNum() >= secondSkuUpGrade.getGptLimitNum() && renewSku.getGptLimitTime() <= secondSkuUpGrade.getGptLimitTime()) {
+                            gptLimitTime = renewSku.getGptLimitTime();
+                            gptLimitNum = renewSku.getGptLimitNum();
+                        }
+                    }
                 }
                 Long packageId = 0l;
                 //降级套餐
@@ -907,6 +934,8 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             giftCardUserRecord.setIsPay(false);
             giftCardUserRecordMapper.updateById(giftCardUserRecord);
         }
+        //校验续费升级规格
+        checkMirrorRenewSku(orderDon);
     }
 
     /**
@@ -1216,11 +1245,11 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             orderDon.setRefundMoney(orderRefundMoney.add(refundMoney));
             orderDonMapper.updateById(orderDon);
 
-            //补差价金额 扣除对应分销提成金额
-            orderDon.setRefundMoney(refundMoney);
-            deductDsPoints(orderDon);
-            //店铺分销提成金额扣除
-            yhShopDistributeService.deductDsMoney(orderDon);
+//            //补差价金额 扣除对应分销提成金额
+//            orderDon.setRefundMoney(refundMoney);
+//            deductDsPoints(orderDon);
+//            //店铺分销提成金额扣除
+//            yhShopDistributeService.deductDsMoney(orderDon);
 
         } else {
             BigDecimal refundBalance = refundMoney;
@@ -1335,4 +1364,26 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         }
         return relation;
     }
+
+    private void checkMirrorRenewSku(OrderDon orderDon) {
+        Long skuId = orderDon.getSkuId();
+        Long orderId = orderDon.getId();
+        OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+                .eq(OrderDonRenewRecord::getOrderId, orderId)
+                .last("limit 1"));
+        if (orderDonRenewRecord != null) {
+            ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
+                    .eq(ChatgptUser::getRelationId, orderDon.getRelationId())
+                    .last("limit 1"));
+            Long presentRenewSkuId = chatgptUser.getRenewSkuId();
+            if (presentRenewSkuId != null) {
+                //存在不同升级套餐
+                GoodsDonSku presentRenewSku = skuMapper.selectById(presentRenewSkuId);
+                if (!ObjectUtil.equal(presentRenewSkuId, skuId)) {
+                    throw BusinessRuntimeException.getInstance("请先退掉用户目前续费升级的{0}规格", presentRenewSku.getSpecVal());
+                }
+            }
+        }
+    }
+
 }

+ 92 - 4
netflix-service/src/main/java/com/cyksj/service/mange/impl/MirrorUserCleatServiceImpl.java

@@ -1,15 +1,20 @@
 package com.cyksj.service.mange.impl;
 
+import cn.hutool.core.date.DateUtil;
 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.mapper.*;
+import com.cyksj.model.entity.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.mange.MirrorUserCleatService;
+import com.cyksj.service.user.UserBindRelationService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * 项目名: yhlxj
  * 文件名: MirrorUserCleatServiceImpl
@@ -18,12 +23,26 @@ import org.springframework.stereotype.Service;
  */
 @Service
 @RequiredArgsConstructor
+@Slf4j
 public class MirrorUserCleatServiceImpl implements MirrorUserCleatService {
 	private final ChatgptUserMapper chatgptUserMapper;
 
 	private final MidjourneyUserMapper midjourneyUserMapper;
 
 	private final RedisService redisService;
+
+	private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final UpgradePackageMapper upgradePackageMapper;
+
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final GroupsMapper groupsMapper;
+
 	@Override
 	public void delMirrorUser(Long goodsId, Long relationId) {
 		//gpt镜像
@@ -46,4 +65,73 @@ public class MirrorUserCleatServiceImpl implements MirrorUserCleatService {
 			}
 		}
 	}
+
+	@Override
+	public void handleRenewUpgradeOrders(OrderDon orderDon) {
+		Long orderId = orderDon.getId();
+		OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+				.eq(OrderDonRenewRecord::getOrderId, orderId)
+				.last("limit 1"));
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(orderDon.getUserId(), null);
+		if (orderDonRenewRecord != null) {
+			ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
+					.eq(ChatgptUser::getRelationId, orderDon.getRelationId())
+					.last("limit 1"));
+			Long presentRenewSkuId = chatgptUser.getRenewSkuId();
+			if (presentRenewSkuId == null) {
+				return;
+			}
+			GroupsRelation relation = groupsRelationMapper.selectById(orderDon.getRelationId());
+			GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+			GoodsDonSku finalSku = skuMapper.selectById(groupsTrips.getSkuId());
+			//是否存在其他续费升级
+			OrderDon otherRenewOrderDon = orderDonRenewRecordMapper.getOtherRenewSku(orderDon.getId(), relation.getId(), userIdList);
+			GoodsDonSku otherRenewSku = null;
+			if (otherRenewOrderDon != null) {
+				otherRenewSku = skuMapper.selectById(otherRenewOrderDon.getSkuId());
+			}
+			GoodsDonSku upgradeOrderDonSku = null;
+			Date renewExpiryTime = null;
+			//是否存在套餐升级包
+			Long packageId = chatgptUser.getPackageId();
+			if (packageId != null && packageId != 0) {
+				UpgradePackage upgradePackage = upgradePackageMapper.selectById(chatgptUser.getPackageId());
+				Long upgradeOrderDonSkuId = upgradePackage.getUpgradeSkuId();
+				upgradeOrderDonSku = skuMapper.selectById(upgradeOrderDonSkuId);
+			}
+			//套餐升级
+			if (upgradeOrderDonSku != null) {
+				log.info("续费升级订单退款,relation_id:{}存在套餐升级", orderDon.getUserId());
+				finalSku = upgradeOrderDonSku;
+			}
+			chatgptUser.setRenewSkuId(null);
+			chatgptUser.setRenewOrderId(null);
+			//续费升级
+			if (otherRenewSku != null) {
+				finalSku = otherRenewSku;
+				log.info("续费升级订单退款,relation_id:{}存在次级续费升级订单", orderDon.getUserId());
+				if (upgradeOrderDonSku != null) {
+					//套餐升级高于其他续费升级
+					if (upgradeOrderDonSku.getMonths() >= otherRenewSku.getMonths() && upgradeOrderDonSku.getGptLimitNum() >= otherRenewSku.getGptLimitNum() && upgradeOrderDonSku.getGptLimitTime() <= otherRenewSku.getGptLimitTime()) {
+						log.info("续费升级订单退款,relation_id:{}存在更高级套餐升级", orderDon.getUserId());
+						finalSku = upgradeOrderDonSku;
+					}
+				}
+				Date payTime = Optional.ofNullable(otherRenewOrderDon.getPayTime()).orElse(otherRenewOrderDon.getCreatedTime());
+				renewExpiryTime = DateUtil.offsetMonth(payTime, otherRenewSku.getMonths());
+				chatgptUser.setRenewOrderId(otherRenewOrderDon.getId());
+				chatgptUser.setRenewSkuId(otherRenewOrderDon.getSkuId());
+			}
+			//还原镜像user
+			chatgptUser.setLimitTime(finalSku.getGptLimitTime());
+			chatgptUser.setLimitNum(finalSku.getGptLimitNum());
+			chatgptUser.setRenewExpiryTime(renewExpiryTime);
+			chatgptUserMapper.updateById(chatgptUser);
+			log.info("还原镜像gptuser套餐成功");
+
+			//将续费有效置为过期
+			orderDonRenewRecord.setIsValid(true);
+			orderDonRenewRecordMapper.updateById(orderDonRenewRecord);
+		}
+	}
 }

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

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange.renew;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.RenewUpgradePackage;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:04
+ */
+public interface RenewUpgradePackageService extends IService<RenewUpgradePackage> {
+}

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/mange/renew/impl/RenewUpgradePackageServiceImpl.java

@@ -0,0 +1,19 @@
+package com.cyksj.service.mange.renew.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.renew.RenewUpgradePackageMapper;
+import com.cyksj.model.entity.RenewUpgradePackage;
+import com.cyksj.service.mange.renew.RenewUpgradePackageService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author zwhui
+ * @date 2024/4/24 15:05
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class RenewUpgradePackageServiceImpl extends ServiceImpl<RenewUpgradePackageMapper, RenewUpgradePackage> implements RenewUpgradePackageService {
+}

+ 2 - 17
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java

@@ -3,31 +3,16 @@ package com.cyksj.service.midjourney;
 import com.cyksj.model.dto.BlendDimensions;
 import com.cyksj.model.entity.MidjourneyUser;
 import com.cyksj.model.entity.MidjourneyUserConversation;
-import com.cyksj.model.response.SubmitResult;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author zwhui
  * @date 2024/4/23 15:44
  */
 public interface MidjourneyService {
-    MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt, String botType,  List<String> base64Array) throws Exception;
+    MidjourneyUser getUser(long userId, Long relationId);
 
-    MidjourneyUserConversation submitDescribe(MidjourneyUser user, String botType, String base64) throws Exception;
+    String getCarLoginUrl(Long userId, Long relationId, String carId);
 
-    MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, String botType, List<String> base64Array) throws Exception;
-
-    MidjourneyUserConversation submitModal(MidjourneyUser user, Long taskId, String prompt, String maskBase64) throws Exception;
-
-    MidjourneyUserConversation submitShorten(MidjourneyUser user, String botType, String prompt) throws Exception;
-
-    List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) throws Exception;
-
-    Object submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception;
-
-    MidjourneyUserConversation cancelConversation(MidjourneyUser user, Long id);
-
-    void notifyHook(String conversation) throws Exception;
 }

+ 6 - 15
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java

@@ -129,7 +129,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
 
     private void addAcount(MidjourneyAccount midjourneyAccount) throws Exception {
         Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
-        String body = HttpRequest.post(HOST + "/mj/account/create").body(Jsons.toJson(accountParam)).execute().body();
+        String body = HttpRequest.post(HOST + "/mj/account/create").header("mj-api-secret", "5a9a3e9b-5a5e-4b6b-9a5a-9a5a5a5a5a5a").body(Jsons.toJson(accountParam)).execute().body();
         log.info("addAccount body:{}", body);
         JSONObject jsonObject = JSONUtil.parseObj(body);
         if (jsonObject.getInt("code") != 1) {
@@ -137,13 +137,9 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         }
     }
     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",
@@ -156,14 +152,8 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
             "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",
@@ -179,11 +169,12 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         param.put("remark", midjourneyAccount.getId());
         param.put("userAgent", User_Agent_LIST.get(new Random().nextInt(User_Agent_LIST.size())));
         param.put("timeoutMinutes", 10);
+        param.put("remixAutoSubmit", Boolean.TRUE);
         return param;
     }
 
     private void delAcount(Long id) {
-        String body = HttpRequest.delete(HOST + "/mj/account/"+id+"/delete").execute().body();
+        String body = HttpRequest.delete(HOST + "/mj/account/"+id+"/delete").header("mj-api-secret", "5a9a3e9b-5a5e-4b6b-9a5a-9a5a5a5a5a5a").execute().body();
         log.info("delAcount body:{}", body);
         JSONObject jsonObject = JSONUtil.parseObj(body);
         if (jsonObject.getInt("code") != 1) {
@@ -192,7 +183,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
     }
 
     private Long getAccount(Long id) throws Exception {
-        String body = HttpRequest.post(HOST + "/mj/account/query").body(Jsons.toJson(MapUtil.of("remark", id))).execute().body();
+        String body = HttpRequest.post(HOST + "/mj/account/query").header("mj-api-secret", "5a9a3e9b-5a5e-4b6b-9a5a-9a5a5a5a5a5a").body(Jsons.toJson(MapUtil.of("remark", id))).execute().body();
         log.info("getAccount body:{}", body);
         JSONObject jsonObject = JSONUtil.parseObj(body);
         return JSONUtil.parseObj(JSONUtil.parseArray(jsonObject.getStr("content")).get(0)).get("id", Long.class);
@@ -201,7 +192,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
     private void updAccount(MidjourneyAccount midjourneyAccount){
         Map<String, Object> accountParam = createAccountParam(midjourneyAccount);
         String body = HttpRequest.put(HOST + "/mj/account/"+midjourneyAccount.getInstanceId()+"/update-reconnect")
-                .body(JSONUtil.toJsonStr(accountParam)).execute().body();
+                .header("mj-api-secret", "5a9a3e9b-5a5e-4b6b-9a5a-9a5a5a5a5a5a").body(JSONUtil.toJsonStr(accountParam)).execute().body();
         log.info("updAccount body:{}", body);
         JSONObject jsonObject = JSONUtil.parseObj(body);
         if (jsonObject.getInt("code") != 1) {
@@ -210,7 +201,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
     }
 
     private String syncInfo(Long id){
-        String body = HttpRequest.post(HOST + "/mj/account/"+id+"/sync-info").execute().body();
+        String body = HttpRequest.post(HOST + "/mj/account/"+id+"/sync-info").header("mj-api-secret", "5a9a3e9b-5a5e-4b6b-9a5a-9a5a5a5a5a5a").execute().body();
         log.info("syncInfo body:{}", body);
         JSONObject jsonObject = JSONUtil.parseObj(body);
         if (jsonObject.getInt("code") != 1) {

+ 114 - 441
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java

@@ -1,40 +1,40 @@
 package com.cyksj.service.midjourney.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.UUID;
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
-import com.cyksj.mapper.MidjourneyUserConversationMapper;
-import com.cyksj.mapper.MidjourneyUserMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.model.dto.BlendDimensions;
 import com.cyksj.model.dto.MessageButton;
-import com.cyksj.model.dto.SubmitModalDTO;
-import com.cyksj.model.entity.MidjourneyAccount;
-import com.cyksj.model.entity.MidjourneyUser;
-import com.cyksj.model.entity.MidjourneyUserConversation;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.response.SubmitResult;
 import com.cyksj.redis.RedisService;
-import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.midjourney.MidjourneyService;
+import com.cyksj.service.sys.SysConfigService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.ejlchina.searcher.BeanSearcher;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Value;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 
 import javax.imageio.stream.FileImageOutputStream;
-import java.io.*;
+import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.*;
@@ -49,474 +49,147 @@ import java.util.stream.Collectors;
 @Slf4j
 @RequiredArgsConstructor
 public class MidjourneyServiceImpl implements MidjourneyService {
-    private static final String RELAX_HOST = "http://43.154.230.104:8080";
-    private static final String FAST_HOST = "https://aigc.api4midjourney.com/api";
-    private static final String FAST_TOKEN = "14a6b469-7cb2-4b99-9238-676c7c5cffef";
-
-    private final MidjourneyUserConversationMapper conversationMapper;
-
-    private static final List<String> progress = List.of("100%");
-
-    private static final List<String> status = List.of("MODAL","CANCEL","FAILURE");
-
-    private final RedisService redisService;
 
     private final MidjourneyUserMapper midjourneyUserMapper;
 
-    @Value("${midjourney.url}")
-    private String midjourneyHost;
-    @Value("${midjourney.cdn}")
-    private String midjourneyCdnHost;
-
-    private final EnvCommonService envCommonService;
+    private final GroupsRelationMapper groupsRelationMapper;
 
-    private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+    private final BeanSearcher beanSearcher;
 
-    private final MidjourneyAccountService midjourneyAccountService;
-
-
-    @Override
-    public MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt,String botType, List<String> base64Array) throws Exception {
-        Map<String, Object> imagineParam = MapUtil.builder(new HashMap<String,Object>())
-                .put("prompt", prompt)
-                .put("state", user.getId())
-                .build();
-        if (CollectionUtil.isNotEmpty(base64Array)) {
-            imagineParam.put("base64Array", base64Array);
-        }
-        SubmitResult result = submit(user.getMode(),"imagine", null,imagineParam);
-        if (user.getMode() == 2) {
-            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-        }
-        return saveConversation(user.getId(), user.getMode(),result,"IMAGINE", StringUtils.EMPTY, botType);
-    }
+    private final UserBindRelationService userBindRelationService;
 
-    public MidjourneyUserConversation saveConversation(Long userId,Integer mode,SubmitResult result, String action,String prompt, String botType) throws Exception {
-        Long taskId = Long.parseLong(result.getResult());
-        Map<String, Object> properties = result.getProperties();
-        MidjourneyUserConversation conversation = new MidjourneyUserConversation()
-                .setUserId(userId).setTaskId(taskId).setAction(action).setPrompt(prompt)
-                .setMode(mode).setStartTime(System.currentTimeMillis()).setProgress("0%")
-                .setStatus(result.getCode() == 21 ? "NOT_START" : "IN_PROGRESS").setTaskId(taskId);
-        if (MapUtil.isNotEmpty(properties)) {
-            conversation.setProperties(Jsons.toJson(properties));
-            conversation.setChannelId(properties.get("discordChannelId") == null ? null : Long.parseLong(properties.get("discordChannelId").toString()))
-                    .setInstanceId(properties.get("discordInstanceId") == null ? null : Long.parseLong(properties.get("discordInstanceId").toString()));
-        }
-        if (conversation.getInstanceId() == null) {
-            conversation.setInstanceId(result.getInstanceId());
-        }
-        conversationMapper.insert(conversation);
-        return conversation;
-    }
+    private final GroupsMapper groupsMapper;
 
+    private final UserMapper userMapper;
 
-    @Override
-    public MidjourneyUserConversation submitDescribe(MidjourneyUser user, String botType, String base64) throws Exception {
-        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
-                .put("state", user.getId())
-                .put("base64", base64)
-                .build();
-        SubmitResult result = submit(user.getMode(),"describe", null, param);
-        if (user.getMode() == 2) {
-            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-        }
-        return saveConversation(user.getId(), user.getMode(),result,"DESCRIBE", StringUtils.EMPTY, botType);
-    }
+    private final RedisService redisService;
 
-    @Override
-    public MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, String botType, List<String> base64Array) throws Exception {
-        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
-                .put("base64Array", base64Array)
-                .put("state", user.getId())
-                .build();
-        if (dimensions != null) {
-            param.put("dimensions", dimensions);
-        }
-        SubmitResult result = submit(user.getMode(),"blend", null, param);
-        if (user.getMode() == 2) {
-            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-        }
-        return saveConversation(user.getId(), user.getMode(),result,"BLEND", StringUtils.EMPTY, botType);
-    }
+    private final GoodsDonSkuMapper skuMapper;
 
-    @Override
-    public MidjourneyUserConversation submitModal(MidjourneyUser user, Long taskId, String prompt, String maskBase64) throws Exception {
-        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
-                .put("taskId", taskId)
-                .put("state", user.getId())
-                .build();
-        if (StringUtils.isNotBlank(prompt)) {
-            param.put("prompt", prompt);
-        }
-        if (StringUtils.isNotBlank(maskBase64)) {
-            param.put("maskBase64", maskBase64);
-        }
-        SubmitResult result = submit(user.getMode(),"modal", null, param);
-        if (user.getMode() == 2) {
-            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-        }
-        return saveConversation(user.getId(),  user.getMode(),result,"MODAL", StringUtils.EMPTY, StringUtils.EMPTY);
-    }
+    private final SysConfigService sysConfigService;
 
     @Override
-    public MidjourneyUserConversation submitShorten(MidjourneyUser user, String botType, String prompt) throws Exception {
-        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
-                .put("prompt", prompt)
-                .put("state", user.getId())
-                .build();
-        SubmitResult result = submit(user.getMode(),"shorten", null, param);
-        if (user.getMode() == 2) {
-            redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-        }
-        return saveConversation(user.getId(), user.getMode(), result,"SHORTEN", StringUtils.EMPTY, botType);
-    }
+    public MidjourneyUser getUser(long userId, Long relationId) {
+        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
+        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
+        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
 
-    /**
-     * 恢复次数
-     */
-    public void recoverUserLimit(Long id,Integer mode,Long num){
-        if (mode == 1){
-            redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + id, 1L);
-            midjourneyUserMapper.incrFastNum(id, 1);
-        }
-        if (mode == 2){
-            if (num != null){
-                redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + id, 1L);
-                midjourneyUserMapper.incrRelaxNum(id, 1);
-            }
+        if (goodsDonSku != null && goodsDonSku.getGoodsId() == 26 && goodsDonSku.getIsMirror()) {
+            return getMidjourneyUser(userId, relationId, groupsRelation, goodsDonSku);
+        } else {
+            throw BusinessRuntimeException.getInstance("服务器出了点问题");
         }
     }
-//    /**
-//     * 同步数据库
-//     */
-//    public void syncUser(Long id,Integer mode,Long num){
-//        log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
-//        if (num == null){
-//            return;
-//        }
-//        LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
-//                .eq(MidjourneyUser::getId, id);
-//        if (mode == 1){
-//            wrapper.set(MidjourneyUser::getMjFastNum, num);
-//        }
-//        if (mode == 2){
-//            wrapper.set(MidjourneyUser::getMjRelaxNum, num);
-//        }
-//        midjourneyUserMapper.update(null, wrapper);
-//    }
 
     @Override
-    public Object submitAction(MidjourneyUser user, Long taskId, String customId, Long num, String botType) throws Exception {
-        MidjourneyUserConversation conversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getTaskId, taskId).last("limit 1"));
-        if (conversation == null) {
-            throw BusinessRuntimeException.getInstance("关联任务不存在或已失效");
-        }
-        if (!user.getMode().equals(conversation.getMode())) {
-            throw BusinessRuntimeException.getInstance("当前出图模式与关联任务出图模式不符");
-        }
-        AtomicBoolean modalFlag = new AtomicBoolean(false);
-        if (StringUtils.isNotBlank(conversation.getButtons())){
-            List<MessageButton> messageButtons = Jsons.parseList(conversation.getButtons(), MessageButton.class);
-            messageButtons.forEach(button -> {
-                if (button.getCustomId().equals(customId)) {
-                    log.info("action customId:{}", customId);
-                    button.setStyle(3);
-                    if (!"Vary (Region)".equals(button.getLabel()) && !"Custom Zoom".equals(button.getLabel())) {
-                        modalFlag.set(true);
-                    }
-                }
-            });
-            conversation.setButtons(Jsons.toJson(messageButtons));
-        }
-        if (customId.contains("BOOKMARK")) {
-            conversation.setBookmark(true);
-            conversationMapper.updateById(conversation);
-            return null;
-        }
-        Map<String, Object> param = MapUtil.builder(new HashMap<String,Object>())
-                .put("taskId", taskId)
-                .put("state", user.getId())
-                .put("customId", customId)
-                .build();
-        SubmitResult result = submit(user.getMode(),"action", conversation.getInstanceId(),param);
-        if (result.getCode() == 21) {
-            if (user.getMode() == 2 && modalFlag.get()){
-                MidjourneyUserConversation modal = submitModal(user, Long.valueOf(result.getResult()), conversation.getPrompt() + " --v 6", null);
-                log.info("action-modal:{}", modal);
-                return modal;
-            }else {
-                // 以上操作有弹窗确认,恢复次数
-                recoverUserLimit(user.getId(), user.getMode(),num);
-            }
-        }else {
-            //syncUser(user.getId(), user.getMode(),num);
-            if (!customId.contains("upsample") && user.getMode() == 2) {
-                redisService.hincr(RedisService.key.MIDJOURNEY_ACCOUNT.getName(), result.getInstanceId().toString(), 1.0);
-            }
-        }
-        saveConversation(user.getId(), user.getMode(), result,"ACTION", StringUtils.EMPTY, botType);
-        return result;
-    }
+    public String getCarLoginUrl(Long userId, Long relationId, String carId) {
 
+        GroupsRelation groupsRelation = getGroupsRelation(userId, relationId);
+        GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
+        GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
+        if (goodsDonSku != null && goodsDonSku.getIsMirror() && goodsDonSku.getIsCar()) {
+            MidjourneyUser midjourneyUser = getMidjourneyUser(userId, relationId, groupsRelation, goodsDonSku);
 
-    public SubmitResult submit(Integer mode,String action,Long instanceId, Map<String, Object> param) throws Exception {
-        String url = "";
-        String accountWithMinUsage = "";
-        if (mode == 1) {
-            param.put("mode", "FAST");
-            url = FAST_HOST;
-        } else if (mode == 2) {
-            url = RELAX_HOST;
-            //慢速查询在使用次数最少的账号
-            accountWithMinUsage = getAccountWithMinUsage(instanceId);
-            param.put("accountFilter",MapUtil.builder(new HashMap<String,Object>())
-                    .put("instanceId",accountWithMinUsage).build());
-        }
-        url = url + getActionUrl(action);
-        param.put("notifyHook",midjourneyHost +(EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8081":"/8082") + "/api/applets/midjourney/notifyHook");
-        String body = HttpRequest.post(url).body(Jsons.toJson(param)).header("Authorization", FAST_TOKEN).execute().body();
-        log.info("action body:{}", body);
-        SubmitResult submitResult = Jsons.parseObject(body, SubmitResult.class);
-        int code = submitResult.getCode();
-        if (code != 1 && code != 21 && code != 22) {
-            if (code == 3) {
-                if(mode == 2 && StringUtils.isNotBlank(accountWithMinUsage)){
-                    redisService.hdel(RedisService.key.MIDJOURNEY_ACCOUNT.getName(),accountWithMinUsage);
-                    String finalAccountWithMinUsage = accountWithMinUsage;
-                    TASK_EXECUTOR.execute(() -> {
-                        MidjourneyAccount account = midjourneyAccountService.getOne(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getInstanceId, finalAccountWithMinUsage).last("limit 1"));
-                        midjourneyAccountService.updateStatus(account.getId());
-                    });
-                }
-                throw BusinessRuntimeException.getInstance("账号不存在");
-            }
-            if (code == 4) {
-                throw BusinessRuntimeException.getInstance(submitResult.getDescription());
-            }
-            if (code == 24) {
-                JSONObject jsonObject = JSONUtil.parseObj(submitResult.getResult());
-                throw BusinessRuntimeException.getInstance("prompt包含敏感词:"+jsonObject.getStr("bannedWord"));
-            }
-            log.error("action:" + action + " error message:" + submitResult.getDescription());
-            throw BusinessRuntimeException.getInstance("队列已满,请稍后尝试");
-        }
-        if (StringUtils.isNotBlank(accountWithMinUsage) && mode == 2) {
-            submitResult.setInstanceId(Long.valueOf(accountWithMinUsage));
-        }
-        return submitResult;
-    }
-
-    public String getAccountWithMinUsage(Long instanceId) {
-        String key = RedisService.key.MIDJOURNEY_ACCOUNT.getName();
-        try {
-            // 获取所有账号ID和使用次数
-            Map<Object, Object> accountsUsage = redisService.hmget(key);
-
-            if (accountsUsage == null || accountsUsage.isEmpty()) {
-                accountsUsage = midjourneyAccountService.list(Wrappers.lambdaQuery(MidjourneyAccount.class).eq(MidjourneyAccount::getStatus,Boolean.TRUE)).stream().collect(Collectors.toMap(k -> k.getInstanceId().toString(), v -> 0));
-                // 保存所有账号ID和使用次数
-                redisService.hmset(key, accountsUsage);
-            }
-
-            // 找到使用次数最少的账号ID
-            String minAccountId = null;
-            if (instanceId != null) {
-                minAccountId = instanceId.toString();
-            }else {
-                int minUsage = Integer.MAX_VALUE;
-                for (Map.Entry<Object, Object> entry : accountsUsage.entrySet()) {
-                    int usage = Integer.parseInt(entry.getValue().toString());
-                    if (usage < minUsage) {
-                        minUsage = usage;
-                        minAccountId = entry.getKey().toString();
+            String DOMAIN = "https://mj.yinhedvd.com";
+            try {
+                SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "mirror_mj_domain"));
+                if (sysConfig != null) {
+                    String sysValue = sysConfig.getSysValue();
+                    if (JSONUtil.isJsonArray(sysValue)) {
+                        List<String> domainList = JSONUtil.parseArray(sysValue).toList(String.class);
+                        DOMAIN = domainList.get(RandomUtil.randomInt(domainList.size()));
                     }
                 }
+            } catch (Exception e) {
+                log.error("随机抽取域名错误. msg:{}", StringUtil.getErrorText(e));
             }
-            return minAccountId;
-        } catch (Exception e) {
-            throw BusinessRuntimeException.getInstance("获取账号失败");
+            log.info("domain:{},用户:{},所在车次:{},座位id:{},在{}获取跳转Midjourney镜像的登录url", DOMAIN, userId, groupsTrips.getId(), relationId, DateTime.now());
+            return DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + midjourneyUser.getUserToken();
+        } else {
+            throw BusinessRuntimeException.getInstance("服务器出了点问题");
         }
     }
-    private String getActionUrl(String action) {
-         switch (action) {
-            case "imagine":
-                return "/mj/submit/imagine";
-            case "action":
-                return "/mj/submit/action";
-            case "describe":
-                return "/mj/submit/describe";
-            case "blend":
-                return"/mj/submit/blend";
-            case "modal":
-                return "/mj/submit/modal";
-            case "shorten":
-                return "/mj/submit/shorten";
-            default:  throw new IllegalArgumentException("Unknown action: " + action);
-        }
-    }
-    @Override
-    public List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) {
-        List<MidjourneyUserConversation> list = new ArrayList<>();
-        ids.forEach(id ->{
-            String queryKey = RedisService.key.MIDJOURNEY_QUERY.getName();
-            Long count = redisService.incr(queryKey + id, 1L);
-            if (count%5 == 0) {
-                try {
-                    listByIds(mode,List.of(id)).forEach(json ->{
-                        JSONObject jsons = JSONUtil.parseObj(json);
-                        MidjourneyUserConversation conversation = JSONUtil.toBean(jsons, MidjourneyUserConversation.class);
-                        if (StringUtil.isNotBlank(conversation.getImageUrl())) {
-                            conversation.setImageUrl(conversation.getImageUrl().replace("cdn.discordapp.com", "mj.galaxydvd.com"));
-                        }
-                        conversation.setUserId(jsons.getLong("state"));
-                        conversation.setTaskId(jsons.getLong("id"));
-                        list.add(conversation);
-                        TASK_EXECUTOR.execute(() -> {
-                            try {
-                                sync(conversation);
-                            } catch (IOException e) {
-                                throw new RuntimeException(e);
-                            }
-                        });
-                    });
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }else {
-                list.add((MidjourneyUserConversation) redisService.get(RedisService.key.MIDJOURNEY_CONVERSATION.getName() + id));
-            }
-        });
-        return list;
-    }
 
 
-    public void sync(MidjourneyUserConversation conversation) throws IOException {
-        if ((StringUtils.isNotBlank(conversation.getProgress()) && progress.contains(conversation.getProgress())) || status.contains(conversation.getStatus())) {
-            log.info("同步任务:{},进度:{}",conversation.getTaskId(),conversation.getProgress());
-            Long userId = conversation.getUserId();
-            MidjourneyUserConversation dbConversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getTaskId, conversation.getTaskId())
-                    .eq(MidjourneyUserConversation::getUserId, userId).orderByDesc(MidjourneyUserConversation::getId).last("limit 1"));
-            if (dbConversation != null) {
-                if ("SUCCESS".equals(dbConversation.getStatus()) || "FAILURE".equals(dbConversation.getStatus()) || "MODAL".equals(dbConversation.getStatus())) {
-                    return;
-                }
-                conversation.setId(dbConversation.getId());
-                conversationMapper.updateById(conversation);
-                TASK_EXECUTOR.execute(() -> {
-                    try {
-                        String imageUrl = conversation.getImageUrl();
-                        if (StringUtil.isNotBlank(imageUrl)) {
-                            conversation.setImageUrl(uploadPic(imageUrl, "conversation"+dbConversation.getId()));
-                            conversationMapper.updateById(conversation);
-                        }
-                    } catch (IOException e) {
-                        log.error("上传图片失败",e);
-                    }
-                });
-                //失败返还次数
-                if ("FAILURE".equals(conversation.getStatus())){
-                    Object num = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + userId);
-                    LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
-                            .eq(MidjourneyUser::getId, userId);
-                    Integer mode = dbConversation.getMode();
-                    if (mode == 1){
-                        num =  redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + userId, 1L);
-                        wrapper.set(MidjourneyUser::getMjFastNum, num);
-                    }
-                    if (mode == 2){
-                        if (num != null) {
-                            num = redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + userId, 1L);
-                            wrapper.set(MidjourneyUser::getMjRelaxNum, num);
-                        }
-                    }
-                    midjourneyUserMapper.update(null, wrapper);
-                }
-            }
+    /**
+     * 获取车位信息
+     *
+     * @param userId
+     * @param relationId
+     * @return
+     */
+    private GroupsRelation getGroupsRelation(Long userId, Long relationId) {
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getId, relationId));
+        if (groupsRelation == null) {
+            throw BusinessRuntimeException.getInstance("车票不存在");
         }
+        return groupsRelation;
     }
 
-
-    private String uploadPic(String url, String prefix) throws IOException {
-        byte[] body = HttpUtil.downloadBytes(url);
-        Path tempFile = Files.createTempFile(Path.of("/mnt/picture"),prefix, ".png");
-        File file = tempFile.toFile();
-        try (FileImageOutputStream imageOutput = new FileImageOutputStream(file)) {
-            imageOutput.write(body, 0, body.length);
+    /**
+     * 获取车队信息
+     *
+     * @param groupsRelation
+     * @return
+     */
+    private GroupsTrips getGroupsTrips(GroupsRelation groupsRelation) {
+        GroupsTrips groupsTrips = groupsMapper.selectById(groupsRelation.getGroupsId());
+        if (groupsTrips == null) {
+            throw BusinessRuntimeException.getInstance("车队异常");
         }
-        return midjourneyCdnHost + "/picture/" + file.getName();
+        return groupsTrips;
     }
 
-    private static List<String> uploadBase64Pic(List<String> base64Array) throws IOException {
-        List<String> list = new ArrayList<>();
-        for (String base64 : base64Array) {
-            String fileExt = "jpeg";
-            if (base64.contains(";")){
-                fileExt = base64.split(";")[0].split("/")[1];
-                base64 = base64.split(",")[1];
-            }
-            byte[] body = Base64.getDecoder().decode(base64);
-            Path tempFile = Files.createTempFile(UUID.randomUUID().toString(), "." + fileExt);
-            try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
-                imageOutput.write(body, 0, body.length);
-            }
-            Map<String, Object> paramMap = new HashMap<>();
-            paramMap.put("file", tempFile.toFile());
-            String json = HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap);
-            list.add(new JSONObject(json).getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl"));
+    private MidjourneyUser getMidjourneyUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
+        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, relationId));
+        User user = userMapper.selectById(userId);
+        if (midjourneyUser == null) {
+            midjourneyUser = createMidjourneyUser(groupsRelation, user, goodsDonSku);
+        } else {
+            updateMidjourneyUser(groupsRelation, user, midjourneyUser);
         }
-        return list;
-    }
-    public JSONArray listByIds(Integer mode,List<Long> ids) throws Exception {
-        Map<String, Object> param = MapUtil.builder(new HashMap<String, Object>()).put("ids", ids).build();
-        String body = HttpRequest.post((mode == 1 ? FAST_HOST : RELAX_HOST) + "/mj/task/list-by-condition").header("Authorization", FAST_TOKEN).body(Jsons.toJson(param)).execute().body();
-        log.info("listByIds body:{}", body);
-        return JSONUtil.parseArray(body);
+        return midjourneyUser;
     }
 
-    @Override
-    public MidjourneyUserConversation cancelConversation(MidjourneyUser user, Long id) {
-        MidjourneyUserConversation conversation = conversationMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUserConversation.class).eq(MidjourneyUserConversation::getId, id));
-        if (conversation == null) {
-            throw BusinessRuntimeException.getInstance("会话不存在");
+    /**
+     * 创建MidjourneyUser
+     */
+    private synchronized MidjourneyUser createMidjourneyUser(GroupsRelation groupsRelation, User user, GoodsDonSku goodsDonSku) {
+        MidjourneyUser midjourneyUser = new MidjourneyUser();
+        midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
+        midjourneyUser.setName(user.getNickname());
+        midjourneyUser.setImg("https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png");
+        midjourneyUser.setRelationId(groupsRelation.getId());
+        midjourneyUser.setUserToken(UUID.randomUUID().toString());
+        if (groupsRelation.getAqType() == 2) {
+            //fast模式 5次
+            midjourneyUser.setMjFastNum(5);
+            midjourneyUser.setMjRelaxNum(0);
+        } else {
+            midjourneyUser.setMjFastNum(goodsDonSku.getMjFastNum());
+            midjourneyUser.setMjRelaxNum((goodsDonSku.getMjRelaxNum() == null || goodsDonSku.getMjRelaxNum() == 0) ? null : goodsDonSku.getMjRelaxNum());
+        }
+        midjourneyUser.setAqType(groupsRelation.getAqType());
+        try {
+            midjourneyUserMapper.insert(midjourneyUser);
+        } catch (DuplicateKeyException e) {
         }
-        if (!Objects.equals(conversation.getUserId(), user.getId())) {
-            throw BusinessRuntimeException.getInstance("不是您的会话");
+        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());
         }
-        conversation.setStatus("CANCEL");
-        conversationMapper.updateById(conversation);
-        TASK_EXECUTOR.execute(() -> {
-            cancel(user.getMode(),conversation.getTaskId());
-        });
-        return conversation;
+        return midjourneyUser;
     }
 
-    public void cancel(Integer mode,Long taskId) {
-        String body = HttpUtil.post(mode == 1 ? FAST_HOST : RELAX_HOST + "/mj/task/"+taskId+"/cancel",MapUtil.empty());
-        log.info("cancel body:{}", body);
-        JSONObject jsonObject = JSONUtil.parseObj(body);
-        if (jsonObject.getInt("code") != 1) {
-            throw BusinessRuntimeException.getInstance("cancel error message:" + jsonObject.getStr("description"));
-        }
+    private void updateMidjourneyUser(GroupsRelation groupsRelation, User user, MidjourneyUser midjourneyUser) {
+        midjourneyUser.setName(user.getNickname());
+        midjourneyUser.setImg("https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png");
+        midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
+        midjourneyUserMapper.updateById(midjourneyUser);
+        midjourneyUser.setAqType(groupsRelation.getAqType());
+        redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken(), midjourneyUser, RedisService.key.MIDJOURNEY_USER.getTimeout());
     }
 
-    @Override
-    public void notifyHook(String json) {
-        log.info("notifyHook:{}", json);
-        JSONObject jsons = JSONUtil.parseObj(json);
-        MidjourneyUserConversation conversation = JSONUtil.toBean(jsons, MidjourneyUserConversation.class);
-        conversation.setUserId(jsons.getLong("state"));
-        conversation.setTaskId(jsons.getLong("id"));
-        if (StringUtil.isNotBlank(conversation.getImageUrl())) {
-            conversation.setImageUrl(conversation.getImageUrl().replace("cdn.discordapp.com", "mj.galaxydvd.com"));
-        }
-        redisService.set(RedisService.key.MIDJOURNEY_CONVERSATION.getName() + conversation.getTaskId(), conversation,RedisService.key.MIDJOURNEY_CONVERSATION.getTimeout());
-        TASK_EXECUTOR.execute(() -> {
-            try {
-                sync(conversation);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        });
-    }
 }

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

@@ -104,4 +104,6 @@ public interface OrderDonService extends IService<OrderDon> {
     void closeUpgradeOrder(Long orderId, Long userId);
 
     UpgradeOrderDetailView getUpgradeOrderDetail(Long orderId, Long userId);
+
+	OrderDon submitRenewUpgrade(OrderPayRequest payRequest);
 }

+ 10 - 2
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderCommonServiceImpl.java

@@ -95,7 +95,11 @@ public class OrderCommonServiceImpl implements OrderCommonService {
 						if (sku.getDays() != null && sku.getDays() > 0) {
 							refundExpiryTime = DateUtil.offsetDay(expiryTime, -sku.getDays() * num);
 						} else {
-							refundExpiryTime = DateUtil.offsetMonth(expiryTime, -sku.getMonths() * num);
+							if (sku.getGoodsId() == 1 && sku.getMonths() == 1) {
+								refundExpiryTime = DateUtil.offsetDay(expiryTime, -30);
+							} else {
+								refundExpiryTime = DateUtil.offsetMonth(expiryTime, -sku.getMonths() * num);
+							}
 						}
 						if (now.isBefore(refundExpiryTime)) {
 							isFlag = false;
@@ -121,7 +125,11 @@ public class OrderCommonServiceImpl implements OrderCommonService {
 						if (sku.getDays() != null && sku.getDays() > 0) {
 							expiryTime = DateUtil.offsetDay(expiryTime, -sku.getDays() * num);
 						} else {
-							expiryTime = DateUtil.offsetMonth(expiryTime, -sku.getMonths() * num);
+							if (sku.getGoodsId() == 1 && sku.getMonths() == 1) {
+								expiryTime = DateUtil.offsetDay(expiryTime, -30);
+							} else{
+								expiryTime = DateUtil.offsetMonth(expiryTime, -sku.getMonths() * num);
+							}
 						}
 						relation.setExpiryTime(expiryTime);
 						groupsRelationMapper.updateById(relation);

+ 188 - 25
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -57,6 +57,7 @@ import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubRewardsMapper;
 import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubWaitingMapper;
 import com.cyksj.mapper.market.task.TaskTypeMapper;
 import com.cyksj.mapper.market.task.UserBindDetailMapper;
+import com.cyksj.mapper.renew.RenewUpgradePackageMapper;
 import com.cyksj.mapper.shop.YhShopGoodsSkuMapper;
 import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.*;
@@ -317,6 +318,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
 
+	private final RenewUpgradePackageMapper renewUpgradePackageMapper;
+
+	private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -453,6 +458,22 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			payRequest.setDonMoney(sku.getPrice());
 		}
 
+//		//如 mj标准6人月付 价格特殊处理
+//		if (Constant.SPECIAL_PRICE_SKU_IDS.contains(sku.getId())) {
+//			UserDistributeShared distributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class)
+//					.eq(UserDistributeShared::getUserId, userId)
+//					.last("limit 1"));
+//			if (distributeShared != null) {
+//				SysConfig one = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+//						.eq(SysConfig::getSysKey, Constant.MJ_SPECIAL_SKU_PRICE_KEY)
+//						.last("limit 1"));
+//				if (one != null && StrUtil.isNotBlank(one.getSysValue())) {
+//					GoodsDonPriceDto goodsDonPriceDto = Jsons.parseObject(one.getSysValue(), GoodsDonPriceDto.class);
+//					payRequest.setDonMoney(goodsDonPriceDto.getPrice());
+//				}
+//			}
+//		}
+
 		//租赁商品
 		if (goodsDon.getType() == 4) {
 			//是否已实名认证过
@@ -1017,6 +1038,18 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//订单金额为0 且订单为已完成 更新虚物车票
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
 			OrderDon updateOrder = orderDonMapper.selectById(orderDon.getId());
+			//mj镜像续费订单
+			if(orderDon.getOrderType() == 2 && orderDon.getGoodsId() == 26){
+				GroupsRelation groupsRelation = groupsRelationMapper.selectById(orderDon.getRelationId());
+				if(groupsRelation != null){
+					Date expiryTime = groupsRelation.getExpiryTime();
+
+					//mj续费订单当天过期直接加次数
+					if (expiryTime != null && DateUtil.isSameDay(new Date(), expiryTime)) {
+						mjRenewOrder(orderDon);
+					}
+				}
+			}
 			updateOrder.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
 			updateGroupsTicket(updateOrder, goodsDon, sku);
 			orderDonMapper.updateById(updateOrder);
@@ -1419,19 +1452,26 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
 					GoodsDonSku donSku = goodsDonSkuMapper.selectById(order.getSkuId());
 					Date newDate;
+					Date skuNewExpiryTime;
 					//天数、月份
 					if (donSku.getDays() != null && donSku.getDays() > 0) {
 						newDate = DateUtil.offsetDay(expiryTime, donSku.getDays() * order.getNum());
+						skuNewExpiryTime = DateUtil.offsetDay(DateTime.now(), donSku.getDays() * order.getNum());
 					} else {
 						//奈飞月付 按30天计算
 						if (sku.getId() == 4) {
 							newDate = DateUtil.offsetDay(expiryTime, 30 * order.getNum());
+							skuNewExpiryTime = DateUtil.offsetDay(DateTime.now(), 30 * order.getNum());
 						} else {
 							newDate = DateUtil.offset(expiryTime, DateField.MONTH, donSku.getMonths() * order.getNum());
+							skuNewExpiryTime = DateUtil.offset(DateTime.now(), DateField.MONTH, donSku.getMonths() * order.getNum());
 						}
 					}
 					relation.setExpiryTime(newDate);
 					relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
+
+					//镜像续费升级
+					handleMirrorRenew(sku, order, groupsTrips, relation.getId(), skuNewExpiryTime);
 				} else if (GroupsTrips.Status.waiting.equals(groupsTrips.getStatus())) {
 					log.info("车位groupsId:{}未发车,修改订单号orderNo:{}订单为已付款状态:{}", groupsTrips.getId(), order.getOrderNo());
 					order.setStatus(OrderDon.Status.hasPayment);
@@ -1474,31 +1514,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				}
 			}
 		}
-
-//		//新订单产生 发送模板消息给用户、客服
-//		User user = userMapper.selectById(order.getUserId());
-//		if (user != null) {
-//			THREAD_POOL_TASK_EXECUTOR.execute(() -> {
-//				try {
-//					//发送至用户消息
-//					templateCommonService.newOderSendMsgByType(order, goodsDon, user, user.getOpenId(), false);
-//				} catch (Exception e) {
-//					log.error("向用户发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
-//				}
-//			});
-//		}
-//		THREAD_POOL_TASK_EXECUTOR.execute(() -> {
-//			try {
-//				//发送至客服消息
-//				List<CustomerService> customerServices = customerServiceMapper.selectList(null);
-//				for (CustomerService customerService : customerServices) {
-//					log.info("向客服{}发送新订单消息通知..", customerService.getNickName());
-//					templateCommonService.newOderSendMsgByType(order, goodsDon, user, customerService.getOpenId(), true);
-//				}
-//			} catch (Exception e) {
-//				log.error("向客服发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
-//			}
-//		});
 	}
 
 	/**
@@ -2429,6 +2444,20 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (orderDon.getIsNoLogin()) {
 			orderDon.setStatus(OrderDon.Status.hasPayment);
 		}
+
+		//mj镜像续费订单
+		if(orderDon.getOrderType() == 2 && orderDon.getGoodsId() == 26){
+			GroupsRelation groupsRelation = groupsRelationMapper.selectById(orderDon.getRelationId());
+			if(groupsRelation != null){
+				Date expiryTime = groupsRelation.getExpiryTime();
+
+				//mj续费订单当天过期直接加次数
+				if (expiryTime != null && DateUtil.isSameDay(new Date(), expiryTime)) {
+					mjRenewOrder(orderDon);
+				}
+			}
+		}
+
 		Long goodsId = goodsDon.getId();
 		if (!orderDon.getIsNoLogin() && sku != null) {
 			//更新座位信息
@@ -2440,6 +2469,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			//客服续费订单
 			handleServiceRenewOrder(orderDon);
 		}
+
 		this.updateById(orderDon);
 
 		//调整指定规格车队下次可 停用车位数的时间
@@ -2556,6 +2586,21 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		}
 	}
+	private void mjRenewOrder(OrderDon orderDon){
+		if (orderDon.getOrderType() == 2 && orderDon.getGoodsId() == 26) {
+			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
+			if (goodsDonSku.getIsMirror()){
+					midjourneyUserMapper.update(null, Wrappers.lambdaUpdate(MidjourneyUser.class)
+							.set(MidjourneyUser::getMjFastNum, goodsDonSku.getMjFastNum())
+							.set(MidjourneyUser::getMjRelaxNum, goodsDonSku.getMjRelaxNum())
+							.eq(MidjourneyUser::getRelationId, orderDon.getRelationId()));
+					MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, orderDon.getRelationId()));
+					log.info("恢复midjourney镜像使用次数: {}", midjourneyUser.getId());
+					redisService.del(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId());
+					redisService.del(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId());
+			}
+		}
+	}
 
 	private void deductGiftCardCash(Long userId, Long gcId, BigDecimal deductCash, BigDecimal gcRemainCash, List<GiftCardOrderUseRecord> gcUseRecords, Boolean isUsed) {
 		Boolean is_update = giftCardUserRecordService.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class)
@@ -3643,6 +3688,83 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
         return beanSearcher.searchFirst(UpgradeOrderDetailView.class, builder.build());
 	}
 
+
+	@Override
+	public OrderDon submitRenewUpgrade(OrderPayRequest payRequest) {
+		Long packageId = payRequest.getPackageId();
+		Long relationId = payRequest.getRelationId();
+		if (relationId == null) {
+			throw BusinessRuntimeException.getInstance("系统异常");
+		}
+		Long userId = payRequest.getUserId();
+		User user = userMapper.selectById(userId);
+		if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+		if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, user);
+		int noPayCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
+				.in(OrderDon::getUserId, userIdList)
+				.eq(OrderDon::getRelationId, payRequest.getRelationId())
+				.eq(OrderDon::getStatus, OrderDon.Status.noPayment.toString()));
+		if (noPayCount > 0) {
+			throw new BusinessRuntimeException("您有未支付订单.");
+		}
+		GroupsRelation groupsRelation = getGroupsRelation(payRequest.getUserId(), payRequest.getRelationId());
+		GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
+		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId());
+		GoodsDon goodsDon = goodsDonMapper.selectById(goodsDonSku.getGoodsId());
+		if (!goodsDonSku.getIsMirror()) {
+			throw BusinessRuntimeException.getInstance("系统异常");
+		}
+		Long renewSkuId = payRequest.getSkuId();
+		GoodsDonSku renewSku = goodsDonSkuMapper.selectById(renewSkuId);
+		//校验同规格
+		if (!ObjectUtil.equal(goodsDonSku.getGoodsId(), renewSku.getGoodsId())) {
+			throw BusinessRuntimeException.getInstance("系统异常");
+		}
+
+		OrderDon orderDon = new OrderDon();
+		orderDon.setUserId(userId);
+		orderDon.setGoodsId(goodsDonSku.getGoodsId());
+		orderDon.setRelationId(relationId);
+		orderDon.setSkuId(renewSkuId);
+		//续费订单
+		orderDon.setOrderType(2);
+		RenewUpgradePackage renewUpgradePackage = renewUpgradePackageMapper.selectOne(Wrappers.lambdaQuery(RenewUpgradePackage.class)
+				.eq(RenewUpgradePackage::getId, packageId)
+				.eq(RenewUpgradePackage::getStatus, 1)
+				.eq(RenewUpgradePackage::getDeleted, 1));
+		if (renewUpgradePackage == null) {
+			throw BusinessRuntimeException.getInstance("续费升级套餐不存在");
+		}
+		BigDecimal price = renewSku.getPrice();
+		orderDon.setOriMoney(price);
+		orderDon.setRealMoney(price);
+		BigDecimal discountPrice = price.multiply(renewUpgradePackage.getDiscount());
+		orderDon.setMoney(discountPrice);
+
+		StringBuilder payTitle = new StringBuilder();
+		payTitle.append(goodsDon.getTitle()).append(renewSku.getSpecVal());
+		orderDon.setPayTitle(payTitle.toString());
+		String donNo = SEQUENCE.nextId().toString();
+		orderDon.setOrderNo(donNo);
+		orderDon.setStatus(OrderDon.Status.noPayment);
+
+		//虚拟商品订单,是否是分销订单
+		setDistributeOrderMark(orderDon, goodsDon.getType(), user.getId());
+
+		//存在余额
+		deductBalancePayOrderMoney(orderDon, payRequest.getBalance(), user);
+
+		orderDonMapper.insert(orderDon);
+		//记录续费升级的规格
+		recordRenewOrderDon(orderDon, renewUpgradePackage, groupsTrips);
+
+		jobManager.addJob(EXPIRY_TIME, () -> {
+			closeOrder(orderDon.getId(), null);
+		});
+		return orderDon;
+	}
+
 	/**
 	 * 试用车票跳转购买正式车票订单记录
 	 */
@@ -3653,4 +3775,45 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			userTrialTicketJumpPayRecordMapper.insert(userTrialTicketJumpPayRecord);
 		}
 	}
+
+	/**
+	 * 记录续费升级的规格
+	 */
+	private void recordRenewOrderDon(OrderDon orderDon, RenewUpgradePackage renewUpgradePackage, GroupsTrips groupsTrips) {
+		OrderDonRenewRecord orderDonRenewRecord = new OrderDonRenewRecord();
+		orderDonRenewRecord.setOrderId(orderDon.getId());
+		orderDonRenewRecord.setUserId(orderDon.getUserId());
+		orderDonRenewRecord.setPackageId(renewUpgradePackage.getId());
+		orderDonRenewRecord.setDiscount(renewUpgradePackage.getDiscount());
+		orderDonRenewRecord.setOriSkuId(groupsTrips.getSkuId());
+		orderDonRenewRecordMapper.insert(orderDonRenewRecord);
+	}
+
+	//镜像续费升级
+	private void handleMirrorRenew(GoodsDonSku sku, OrderDon order, GroupsTrips groupsTrips, Long relationId, Date newDate) {
+		if (sku.getIsMirror() && order.getOrderType() == 2) {
+			OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+					.eq(OrderDonRenewRecord::getOrderId, order.getId())
+					.last("limit 1"));
+			if (orderDonRenewRecord != null) {
+				//同规格续费无需更新
+				if (!ObjectUtil.equal(groupsTrips.getSkuId(), order.getSkuId())) {
+					log.info("用户续费升级订单skuId:{}将用户车票relationId:{}套餐续费升级", order.getSkuId(), relationId);
+					//升级gptUser次数
+					ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
+							.eq(ChatgptUser::getRelationId, relationId)
+							.last("limit 1"));
+					if (chatgptUser != null) {
+						chatgptUser.setLimitTime(sku.getGptLimitTime());
+						chatgptUser.setLimitNum(sku.getGptLimitNum());
+						//记录续费升级过期的时间
+						chatgptUser.setRenewExpiryTime(newDate);
+						chatgptUser.setRenewOrderId(order.getId());
+						chatgptUser.setRenewSkuId(order.getSkuId());
+						chatgptUserMapper.updateById(chatgptUser);
+					}
+				}
+			}
+		}
+	}
 }

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/pay/impl/TransferFuncServiceImpl.java

@@ -36,6 +36,7 @@ import com.cyksj.model.request.ApplyMoneyReq;
 import com.cyksj.model.request.TransferAccountsReq;
 import com.cyksj.model.request.YhShopApplyMoneyReq;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.distribute.UserDistributeReturnMoneyDetailService;
 import com.cyksj.service.pay.TransferFuncService;
 import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.user.UserBenefitsService;
@@ -81,6 +82,8 @@ public class TransferFuncServiceImpl implements TransferFuncService {
 
 	private final SysConfigService sysConfigService;
 
+	private final UserDistributeReturnMoneyDetailService userDistributeReturnMoneyDetailService;
+
 	@Override
 	public Result distributeApply(ApplyMoneyReq applyMoneyReq) throws Exception {
 		applyMoneyReq.setMType(DistributeMoneyApply.MType.ds);
@@ -347,6 +350,7 @@ public class TransferFuncServiceImpl implements TransferFuncService {
 				if (envCommonService.isPrdEnv() && distributeMoneyApply.getVerifyStatus() == DistributeMoneyApply.Status.verifying && distributeMoneyApply.getMoney().compareTo(fourHundred) > 0) {
 					SmsUtil.sendLuoKey2Msg(Constant.ZK_MOBILE, "推广有大额提现申请【银河录像局】");
 				}
+				userDistributeReturnMoneyDetailService.recordDistributeReturnMoney(distributeMoneyApply.getUserId(), distributeMoneyApply.getMoney().negate(), "提现");
 			} catch (Exception e) {
 				userBenefitsService.addDistributePoints(userId, distributeMoneyApply.getPoints());
 				return GatewayResponse.FAIL.newBuilder().setMsg("网络错误,请重试").toResult();

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

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.request.SpecialGoodsTicketReq;
+import com.cyksj.model.request.TicketLoginReq;
 import com.cyksj.model.views.RenewalView;
 import com.cyksj.model.views.UserRecommendGoodsFrontView;
 import com.ejlchina.searcher.SearchResult;
@@ -38,7 +39,7 @@ public interface GroupRelationFrontService {
 	/**
 	 * 获取车票账号登录 验证码
 	 */
-	String getAiVerifyCode(Long userId, Long relationId, Integer type, Boolean sync) throws Exception;
+	String getAiVerifyCode(TicketLoginReq loginReq) throws Exception;
 
 
 	void checkGroupsAvailParkingNum(Long skuId, Long groupsId, Integer availableParkingNum, Integer maxNum);
@@ -59,4 +60,8 @@ public interface GroupRelationFrontService {
 	void getCollegeStudentUserGptTicket(Long userId);
 
 	RenewalView getTicketDetail(long userId, Long relationId);
+
+	GroupsRelation ticketLogin(TicketLoginReq loginReq);
+
+	String outsideTicketVerify(TicketLoginReq loginReq);
 }

+ 100 - 18
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -25,9 +25,11 @@ 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.renew.RenewUpgradePackageMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.SpecialGoodsTicketReq;
+import com.cyksj.model.request.TicketLoginReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.ChatGptAccountService;
@@ -114,9 +116,6 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final UserLoginRecordService userLoginRecordService;
 
-	private final UpgradePackageMapper upgradePackageMapper;
-
-	private final static String VERIFY_CODE_SECRET = "q1w2e3";
 	private final CuiQiuMailService cuiQiuMailService;
 
 	private final UserCertRecordMapper userCertRecordMapper;
@@ -125,8 +124,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final ChatGptAccountService chatGptAccountService;
 
-	//脆球邮箱后缀
-	private final static String CUI_QIU_EMAIL_SUFFIX = "@kindvd.com";
+	private final UpgradePackageMapper upgradePackageMapper;
 
 	private final GoodsDonQaRelateMapper goodsDonQaRelateMapper;
 
@@ -142,6 +140,8 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
 
+	private final RenewUpgradePackageMapper renewUpgradePackageMapper;
+
 	@Override
 	public SearchResult<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account) {
 		User u = userMapper.selectById(userId);
@@ -297,6 +297,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 					UpgradePackage upgradePackage = upgradePackageMapper.selectById(userInfo.getPackageId());
 					ticket.setPackagePrice(upgradePackage.getPrice());
 				}
+				ticket.setIsRenewPackage(userInfo.getIsRenewPackage());
 			}
 			List<GroupsRelationUserView> relationUserViews = groupsRelationMapper.getUserRelationUserViews(ticket.getGroupId(), ticket.getRelationId(), ticket.getUserId(), List.of(GroupsRelation.Status.validity, GroupsRelation.Status.outside));
 			ticket.setRelationViews(relationUserViews);
@@ -313,6 +314,9 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			ticket.setQa(qaId > 0 ? true : false);
 			//是否存在海报
 			ticket.setPosterInfo(setGoodsPoster(ticket, u));
+
+			//续费升级折扣
+			setRenewDiscount(ticket);
 		});
 		userLoginRecordService.saveUserLoginDayRecord(userId);
 		return list;
@@ -516,7 +520,11 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	}
 
 	@Override
-	public String getAiVerifyCode(Long userId, Long relationId, Integer type, Boolean sync) throws Exception {
+	public String getAiVerifyCode(TicketLoginReq loginReq) throws Exception {
+		Long userId = loginReq.getUserId();
+		Long relationId = loginReq.getRelationId();
+		Integer type = loginReq.getType();
+		Boolean sync = loginReq.getSync();
 		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());
@@ -531,8 +539,8 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		if (StrUtil.hasEmpty(account, password)) {
 			throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服...");
 		}
-		if (renewalView.getAccount().contains(CUI_QIU_EMAIL_SUFFIX)) {
-			return cuiQiuMailService.getVerifyCode(renewalView.getAccount(), renewalView.getGoodsId(), type, sync);
+		if (cuiQiuMailService.isCuiQiuEmail(renewalView.getAccount())) {
+			return cuiQiuMailService.getVerifyCode(renewalView.getAccount(), renewalView.getGoodsId(), type, sync, loginReq.getLinkType());
 		}
 		//获取邮箱密码
 		SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
@@ -560,7 +568,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		if (execute.getStatus() != HttpStatus.HTTP_OK) {
 			throw BusinessRuntimeException.getInstance("获取验证码异常,请联系客服...");
 		}
-		String code = getDifferentGoodsCode(renewalView.getGoodsId(), execute.body(), type, sync);
+		String code = getDifferentGoodsCode(renewalView.getGoodsId(), execute.body(), type, sync, loginReq.getLinkType());
 		GroupsRelationLoginCodeRecord record = new GroupsRelationLoginCodeRecord();
 		record.setUserId(userId);
 		record.setRelationId(relationId);
@@ -594,6 +602,9 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	@Override
 	public void adjustGroupsParkingTime(Long relationId, GoodsDonSku sku) {
+		if (sku == null) {
+			return;
+		}
 		Long skuId = sku.getId();
 		//更新GPT Plus10人、4人月付车队状态 待优化
 		if (skuId == 161l || skuId == 178l || skuId == 422l || skuId == 423l) {
@@ -758,33 +769,40 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		return expiryTickets;
 	}
 
-	public String getDifferentGoodsCode(Long goodsId, String body, Integer type, Boolean sync) {
+	public String getDifferentGoodsCode(Long goodsId, String body, Integer type, Boolean sync, Integer linkType) {
 		String code = null;
 		//奈飞
 		if (goodsId == 1) {
 			if (type != null && type == 1) {
-				if (body.contains("輸入此代碼登入") || body.contains("输入此代码登录")) {
+				if (body.contains("輸入此代碼登入") || body.contains("输入此代码登录") || body.contains("Enter this code to sign in")) {
 					code = StrUtil.subBetween(body, "輸入此代碼登入", "請在裝置上輸入上");
 					if (StrUtil.isEmpty(code)) {
 						code = StrUtil.subAfter(body, "输入此代码登录", true);
 					}
+					if (StrUtil.isEmpty(code)) {
+						code = StrUtil.subAfter(body, "Enter this code to sign in", 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)) {
+				String urlPref;
+				//更新装置
+				if (linkType == 1) {
+					urlPref = "https://www.netflix.com/account/update-primary-location";
+					code = StrUtil.subBetween(body, "[" + urlPref, "]");
+				} else {
+					//验证链接
 					urlPref = "https://www.netflix.com/account/travel/verify";
 					code = StrUtil.subBetween(body, "[" + urlPref, "]");
-					if (StrUtil.isEmpty(code)) {
-						throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
-					}
+				}
+				if (StrUtil.isEmpty(code)) {
+					throw BusinessRuntimeException.getInstance("获取认证链接失败,请重新获取");
 				}
 				String url = urlPref + code;
 				//非点击装置同步更新按钮 直接返回链接
-				if (!sync) return url;
+				if (linkType == 2) return url;
 				//失败返回验证链接
 				if (!groupsRelationNetflixService.confirmUpdate(url)) {
 					return url;
@@ -877,6 +895,54 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		return renewalView;
 	}
 
+	@Override
+	public GroupsRelation ticketLogin(TicketLoginReq loginReq) {
+		String account = loginReq.getAccount();
+		String password = loginReq.getPassword();
+		Integer num = loginReq.getNum();
+		Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l);
+		GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num);
+		if (relation == null) {
+			log.info("外部入口使用账号account:{},pwd:{},座位num:{}登录失败...", account, password, num);
+			if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
+				throw BusinessRuntimeException.getInstance("Please enter the correct account information");
+			}
+			throw BusinessRuntimeException.getInstance("请输入正确的账号信息");
+		}
+		return relation;
+	}
+
+	@Override
+	public String outsideTicketVerify(TicketLoginReq loginReq) {
+		String account = loginReq.getAccount();
+		String password = loginReq.getPassword();
+		Integer num = loginReq.getNum();
+		Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l);
+		GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num);
+		if (relation == null) {
+			log.info("外部入口使用账号account:{},pwd:{},座位num:{}同步验证链接失败...", account, password, num);
+			if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
+				throw BusinessRuntimeException.getInstance("This account is no longer valid");
+			}
+			throw BusinessRuntimeException.getInstance("该账号已失效");
+		}
+		loginReq.setUserId(relation.getUserId());
+		loginReq.setRelationId(relation.getId());
+		loginReq.setGoodsId(goodsId);
+		try {
+			String aiVerifyCode = getAiVerifyCode(loginReq);
+			if (StrUtil.isEmpty(aiVerifyCode)) {
+				throw BusinessRuntimeException.getInstance("");
+			}
+			return aiVerifyCode;
+		} catch (Exception e) {
+			if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
+				throw BusinessRuntimeException.getInstance("Please verify that the link was sent");
+			}
+			throw BusinessRuntimeException.getInstance("请校验链接是否已发送");
+		}
+	}
+
 	private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user) {
 		DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
 				.field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build());
@@ -919,4 +985,20 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		return distributePosterGoodsDetailView;
 	}
 
+	private void setRenewDiscount(RenewalView ticket) {
+		if (ticket.getIsMirror()) {
+			RenewUpgradePackage renewUpgradePackage = renewUpgradePackageMapper.selectOne(Wrappers.lambdaQuery(RenewUpgradePackage.class)
+					.eq(RenewUpgradePackage::getGoodsId, ticket.getGoodsId())
+					.eq(RenewUpgradePackage::getStatus, 1)
+					.eq(RenewUpgradePackage::getDeleted, 1)
+					.eq(RenewUpgradePackage::getSkuId, ticket.getSkuId())
+					.orderByAsc(RenewUpgradePackage::getDiscount)
+					.last("limit 1")
+					.select(RenewUpgradePackage::getId, RenewUpgradePackage::getDiscount));
+			if (renewUpgradePackage != null) {
+				ticket.setDiscount(renewUpgradePackage.getDiscount());
+			}
+		}
+	}
+
 }

+ 11 - 8
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java

@@ -155,14 +155,17 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 	 */
 	@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());
+		try {
+			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());
+			}
+		} catch (Exception e) {
 		}
 	}
 }

+ 3 - 3
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -228,15 +228,15 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 		userSysMsgNotifyService.recordUserAccountUpdateSysMsg(account.getGoodsId(), skuId, relations, account.getAccount(), goodsDon.getTitle());
 		for (GroupsRelationView relation : relations) {
 			if (relation.getExpiryTime() == null) {
-				return;
+				continue;
 			}
 			//账号有效期小于5天的人,不发账号替换/改密码短信提醒
 			if (now.after(DateUtil.offsetDay(relation.getExpiryTime(), -5))) {
-				return;
+				continue;
 			}
 			//去掉GPT过滤平台
 			if (Constant.CHANGE_ACCOUNT_PWD_FILTER_GIDS.get(1) == account.getGoodsId()) {
-				return;
+				continue;
 			}
 			if (relation.getUserId() != 0 && relation.getYhsId() == 0 && isPrd) {
 				String msg = String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account.getAccount());

+ 2 - 3
netflix-service/src/main/java/com/cyksj/service/user/impl/BadIntentionOpServiceImpl.java

@@ -6,7 +6,6 @@ import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.SmsUtil;
-import com.cyksj.common.util.StringUtil;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.user.BadIntentionOpService;
 import lombok.RequiredArgsConstructor;
@@ -61,7 +60,7 @@ public class BadIntentionOpServiceImpl implements BadIntentionOpService {
             throw BusinessRuntimeException.getInstance("请先完成图形认证");
         } else {
             //腾讯云图形验证
-            String ip = StringUtil.getInternalAddressByIP(ServletUtil.getClientIP(request));
+            String ip = ServletUtil.getClientIP(request);
             SmsUtil.checkTencentCaptcha(ticket, ip, randStr);
         }
         String dayKey = RedisService.key.PHONE_CODE_USER_NUM_KEY_DAY.getName() + phone;
@@ -87,7 +86,7 @@ public class BadIntentionOpServiceImpl implements BadIntentionOpService {
 
     @Override
     public void isBadOpLoginPhone(HttpServletRequest request, String phone) {
-        String ip = StringUtil.getInternalAddressByIP(ServletUtil.getClientIP(request));
+        String ip = ServletUtil.getClientIP(request);
         log.info("--------------校验ip 是否黑名单------- ip:{}", ip);
         String blackIpKey = RedisService.key.BALCK_USER_IP_KEY + ip;
         if (redisService.hasKey(blackIpKey)) {

+ 30 - 4
netflix-service/src/main/java/com/cyksj/service/user/impl/UserActivityServiceImpl.java

@@ -1,16 +1,15 @@
 package com.cyksj.service.user.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.util.Jsons;
 import com.cyksj.mapper.UserActivityMapper;
+import com.cyksj.mapper.UserActivityRankRobotMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.UserStudentCertRecordMapper;
-import com.cyksj.model.entity.CouponUser;
-import com.cyksj.model.entity.User;
-import com.cyksj.model.entity.UserActivity;
-import com.cyksj.model.entity.UserStudentCertRecord;
+import com.cyksj.model.entity.*;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.user.UserActivityService;
 import lombok.RequiredArgsConstructor;
@@ -19,6 +18,7 @@ import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 项目名: yhlxj
@@ -35,6 +35,8 @@ public class UserActivityServiceImpl extends ServiceImpl<UserActivityMapper, Use
 	private final UserMapper userMapper;
 
 	private final UserStudentCertRecordMapper userStudentCertRecordMapper;
+
+	private final UserActivityRankRobotMapper UserActivityRankRobotMapper;
 	@Override
 	public void sendStudentCertActivity(User user, String dsCode, String school) throws Exception {
 		UserActivity activity = getById(1);
@@ -67,7 +69,31 @@ public class UserActivityServiceImpl extends ServiceImpl<UserActivityMapper, Use
 	@Override
 	public void saveOrUpdateActivity(UserActivity userActivity) throws Exception {
 		checkActivity(userActivity);
+		if (userActivity.getType() == 1) {
+			userActivity.setRewardInfo(Jsons.toJson(userActivity.getRewardInfoList()));
+		}
 		saveOrUpdate(userActivity);
+		if (userActivity.getType() == 1) {
+			List<UserActivityRankRobot> rankRoot = userActivity.getRankRobots();
+			List<Long> collect = null;
+			if (rankRoot != null) {
+				collect = rankRoot.stream().filter(e -> e.getId() != null).map(UserActivityRankRobot::getId).collect(Collectors.toList());
+			}
+			UserActivityRankRobotMapper.delete(Wrappers.lambdaQuery(UserActivityRankRobot.class)
+					.eq(UserActivityRankRobot::getAcId, userActivity.getId())
+					.notIn(CollUtil.isNotEmpty(collect), UserActivityRankRobot::getId, collect));
+
+			if (CollUtil.isNotEmpty(rankRoot)) {
+				rankRoot.forEach(root -> {
+					root.setAcId(userActivity.getId());
+					if (root.getId() != null) {
+						UserActivityRankRobotMapper.updateById(root);
+					} else {
+						UserActivityRankRobotMapper.insert(root);
+					}
+				});
+			}
+		}
 	}
 
 

+ 184 - 0
netflix-web/src/main/java/com/cyksj/web/controller/distribute/DistributeRankController.java

@@ -0,0 +1,184 @@
+package com.cyksj.web.controller.distribute;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserDistributeRankStatisticsRecordMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserDistribute;
+import com.cyksj.model.views.*;
+import com.cyksj.web.util.StpUserUtil;
+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.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.ChronoField;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * server/分销排行
+ * 项目名: yhlxj
+ * 文件名: DistributeRankController
+ * 创建者: JavaZou
+ * 创建时间:2024/7/23 17:10
+ */
+@RestController
+@RequestMapping("/applets/distribute/rank")
+@RequiredArgsConstructor
+public class DistributeRankController {
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final UserDistributeRankStatisticsRecordMapper userDistributeRankStatisticsRecordMapper;
+
+	private final UserMapper userMapper;
+
+	/**
+	 * 分销排行活动详情
+	 */
+	@GetMapping("/get/activity/detail")
+	public Result<UserActivityDistributeDetailView> getActivityDetail() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class)
+				.eq(UserDistribute::getUserId, userId)
+				.eq(UserDistribute::getDeleted, 1)
+				.last("limit 1"));
+		//非普通推广渠道
+		if (userDistribute != null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		String dateStr = DateTime.now().toString();
+		String time = String.format(" and (ua.start_time is null or (ua.start_time < '%s' and ua.end_time > '%s'))", dateStr, dateStr);
+		UserActivityDistributeDetailView view = beanSearcher.searchFirst(UserActivityDistributeDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(UserActivityDistributeDetailView::getType, 1)
+				.put("time", time)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(view);
+	}
+
+	/**
+	 * 个人分销排行详情  以及所属分类排行列表
+	 */
+	@GetMapping("/get/personal")
+	public Result<DistributeUserRankPersonalView> getPersonal(@RequestParam(defaultValue = "0") Integer type, @RequestParam(defaultValue = "week") String statisticsType, @RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "5") Integer limit) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		DistributeUserRankPersonalView distributeUserRankPersonalView = new DistributeUserRankPersonalView();
+		String orderByField = Constant.money;
+		//订单排行
+		if (type == 1) {
+			orderByField = Constant.orders;
+		}
+		String statisticsTime;
+		if (Constant.week.equals(statisticsType)) {
+			//上周一
+			LocalDate monday = LocalDate.now().with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue());
+			statisticsTime = monday.toString();
+		} else {
+			DateTime beginOfMonth = DateUtil.beginOfMonth(DateTime.now());
+			statisticsTime = beginOfMonth.toDateStr();
+		}
+
+		DistributeUserRankView self = Optional.ofNullable(userDistributeRankStatisticsRecordMapper.getSelfRank(orderByField, userId, statisticsTime)).orElseGet(()->{
+			DistributeUserRankView distributeUserRankView = new DistributeUserRankView();
+			User user = userMapper.selectById(userId);
+			distributeUserRankView.setNickname(user.getNickname());
+			distributeUserRankView.setHeadimgurl(user.getHeadimgurl());
+			return distributeUserRankView;
+		});
+		if (self != null && self.getRankId() != null && self.getRankId() <= 10) {
+			self.setIsPrize(true);
+		}
+		distributeUserRankPersonalView.setSelf(self);
+
+		DistributeUserRankView more = userDistributeRankStatisticsRecordMapper.getMoreSelfRank(self.getRankId(), self.getOrders(), self.getMoney(), orderByField, statisticsTime);
+		if (more != null) {
+			if (type == 1) {
+				self.setGapOrders(more.getOrders() - self.getOrders());
+			} else {
+				self.setGapMoney(more.getMoney().subtract(self.getMoney()));
+			}
+		}
+
+		Page<DistributeUserRankView> ranks = userDistributeRankStatisticsRecordMapper.selectDistributeRanks(orderByField, statisticsTime, new Page<>(start, limit));
+		distributeUserRankPersonalView.setRanks(ranks);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(distributeUserRankPersonalView);
+	}
+
+	/**
+	 * 上期获奖名单
+	 */
+	@GetMapping("/get/previous/winners")
+	public Result<List<DistributeUserRankView>> getPreviousWinners(@RequestParam(defaultValue = "0") Integer type, @RequestParam(defaultValue = "week") String statisticsType) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		String lastTime;
+		if (Constant.week.equals(statisticsType)) {
+			//上周一
+			LocalDate monday = LocalDate.now().with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue()).plusWeeks(-1);
+			lastTime = monday.toString();
+		} else {
+			DateTime lastBeginOfMonth = DateUtil.offsetMonth(DateUtil.beginOfMonth(DateTime.now()), -1);
+			lastTime = lastBeginOfMonth.toDateStr();
+		}
+		String orderByField = "money";
+		if (type == 1) {
+			orderByField = "orders";
+		}
+		List<DistributeUserRankView> ranks = userDistributeRankStatisticsRecordMapper.getPreviousWinners(orderByField, lastTime);
+
+		ranks.forEach(rank -> {
+			if (ObjectUtil.equal(userId, rank.getUserId())) {
+				//在前10
+				rank.setIsPrize(true);
+				rank.setUserId(null);
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(ranks);
+	}
+
+	/**
+	 * 获奖明细
+	 */
+	@GetMapping("/get/reward/detail")
+	public Result<SearchResult<UserDistributeRankRewardDetailView>> getUserRewardDetailView() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<UserDistributeRankRewardDetailView> search = beanSearcher.search(UserDistributeRankRewardDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(UserDistributeRankRewardDetailView::getUserId, userId)
+				.orderBy(UserDistributeRankRewardDetailView::getCreatedTime).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 返现明细
+	 */
+	@GetMapping("/get/distribute/returnMoney/detai")
+	public Result<SearchResult<userDistributeReturnMoneyDetail>> getReturnMoneyDetailView() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<userDistributeReturnMoneyDetail> search = beanSearcher.search(userDistributeReturnMoneyDetail.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(userDistributeReturnMoneyDetail::getUserId, userId)
+				.orderBy(userDistributeReturnMoneyDetail::getCreatedTime).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+}

+ 21 - 0
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -18,6 +18,7 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.shop.YhShopGoodsSkuMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.model.entity.*;
@@ -80,6 +81,8 @@ public class GoodsDonController {
 
 	private final UserService userService;
 
+	private final UserDistributeSharedMapper userDistributeSharedMapper;
+
 	private final GoodsDonFrontService goodsDonFrontService;
 
 	private final UserBindRelationService userBindRelationService;
@@ -419,6 +422,24 @@ public class GoodsDonController {
 					}
 				}
 			}
+//			if (fUid != null && Constant.SPECIAL_PRICE_SKU_IDS.contains(sku.getId())) {
+//				UserDistributeShared distributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class)
+//						.eq(UserDistributeShared::getUserId, fUid)
+//						.last("limit 1"));
+//				if (distributeShared != null) {
+//					Optional.ofNullable(sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+//							.eq(SysConfig::getSysKey, Constant.MJ_SPECIAL_SKU_PRICE_KEY)
+//							.last("limit 1"))).ifPresent(sysConfig -> {
+//						if (StrUtil.isNotBlank(sysConfig.getSysValue())) {
+//							try {
+//								GoodsDonPriceDto goodsDonPriceDto = Jsons.parseObject(sysConfig.getSysValue(), GoodsDonPriceDto.class);
+//								sku.setPrice(goodsDonPriceDto.getPrice());
+//							} catch (Exception e) {
+//							}
+//						}
+//					});
+//				}
+//			}
 			return true;
 		}).collect(Collectors.toList()));
 		return GatewayResponse.SUCCESS.newBuilder().toResult(views);

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

@@ -31,6 +31,7 @@ import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.OrderPayRequest;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.model.request.SpecialGoodsTicketReq;
+import com.cyksj.model.request.TicketLoginReq;
 import com.cyksj.model.response.GptStandbyResp;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
@@ -46,7 +47,9 @@ import com.cyksj.service.user.UserService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.operator.LessEqual;
 import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -59,6 +62,8 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
 /**
@@ -125,6 +130,10 @@ public class GroupRelationController {
 
     private final GroupsRelationNetflixService groupsRelationNetflixService;
 
+    private final ChatgptUserMapper chatgptUserMapper;
+
+    private final UpgradeOrderDonMapper upgradeOrderDonMapper;
+
     private final static Sequence SEQUENCE = new Sequence(0);
 
     @RequestMapping("/get/renewal")
@@ -616,10 +625,28 @@ public class GroupRelationController {
     /**
      * 读取车票账号登录验证码
      */
-    @GetMapping("/get/verifyCode/{relationId}")
-    public Result<String> getAiVerifyCode(@PathVariable Long relationId, Integer type, @RequestParam(defaultValue = "0") Boolean sync) throws Exception {
+    @PostMapping("/get/verifyCode")
+    public Result<String> getAiVerifyCode(@RequestBody TicketLoginReq loginReq) throws Exception {
         long userId = StpUserUtil.getLoginIdAsLong();
-        return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(userId, relationId, type, sync));
+        loginReq.setUserId(userId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(loginReq));
+    }
+
+    /**
+     * 车票后台登录
+     */
+    @PostMapping("/ticket/login")
+    public Result<GroupsRelation> ticketLogin(@RequestBody @Validated TicketLoginReq loginReq) {
+        GroupsRelation relation = groupRelationFrontService.ticketLogin(loginReq);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(relation);
+    }
+
+    /**
+     * 奈飞验证校验
+     */
+    @PostMapping("/ticket/verify")
+    public Result<String> outsideTicketVerify(@RequestBody @Validated TicketLoginReq loginReq) {
+        return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.outsideTicketVerify(loginReq));
     }
 
     /**
@@ -855,4 +882,61 @@ public class GroupRelationController {
     public Result<Integer> getPinStatus(@PathVariable String taskId) throws Exception {
         return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationNetflixService.getPinStatus(taskId));
     }
+
+    /**
+     * 可选 续费升级车票
+     */
+    @GetMapping("/get/renew/skus/{relationId}/{skuId}")
+    public Result<List<RenewUpgradePackageFrontView>> getRenewSkus(@PathVariable Long relationId, @PathVariable Long skuId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
+                .eq(ChatgptUser::getRelationId, relationId));
+        if (chatgptUser == null) return GatewayResponse.SUCCESS.newBuilder().toResult();
+        //目前续费升级的规格
+        Long renewSkuId = chatgptUser.getRenewSkuId();
+        GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
+        AtomicInteger minMonths = new AtomicInteger(sku.getMonths());
+        AtomicInteger minNum = new AtomicInteger(chatgptUser.getLimitNum());
+        AtomicLong minTime = new AtomicLong(chatgptUser.getLimitTime());
+        if (renewSkuId != null) {
+            GoodsDonSku presentRenew = goodsDonSkuMapper.selectById(renewSkuId);
+            minMonths.set(presentRenew.getMonths());
+        }
+        if (chatgptUser.getPackageId() != 0) {
+            Long packageId = chatgptUser.getPackageId();
+            UpgradeOrderDon upgradeOrderDon = upgradeOrderDonMapper.selectOne(Wrappers.lambdaQuery(UpgradeOrderDon.class)
+                    .eq(UpgradeOrderDon::getPackageId, packageId)
+                    .eq(UpgradeOrderDon::getRelationId, relationId)
+                    .in(UpgradeOrderDon::getUserId, userIdList)
+                    .last("limit 1"));
+            Long upgradeOrderDonSkuId = upgradeOrderDon.getSkuId();
+            GoodsDonSku upgradeSku = goodsDonSkuMapper.selectById(upgradeOrderDonSkuId);
+            if (upgradeSku != null) {
+                if (upgradeSku.getMonths() > minMonths.get()) {
+                    minMonths.set(upgradeSku.getMonths());
+                }
+            }
+        }
+        List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
+        renewUpgradePackageFrontViews.forEach(renew -> {
+            try {
+                //年付展示
+                MapBuilder builder = MapUtils.builder();
+                if (minMonths.get() == 12) {
+                    builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual);
+                }else {
+                    builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterThan);
+                }
+                List<RenewUpgradePackageFrontView.RenewSkuView> renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder
+                        .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitNum, minNum.get()).op(Operator.GreaterEqual)
+                        .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitTime, minTime.get()).op(LessEqual.class)
+                        .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, Jsons.parseList(renew.getUpgradeSkuIds(), Long.class)).op(Operator.InList)
+                        .build());
+                renew.setRenewSkus(renewSkuViews);
+            } catch (Exception e) {
+            }
+        });
+        return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews);
+    }
 }

+ 37 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -28,6 +28,8 @@ import com.cyksj.mapper.manage.RealGoodsOrderHandleMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.mapper.shop.YhShopMapper;
+import com.cyksj.model.dto.OriSkuDto;
+import com.cyksj.model.dto.RenewOriOrderSkuDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.excel.*;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
@@ -114,10 +116,12 @@ public class CmsOrderController {
 
 	private final UserBindRelationService userBindRelationService;
 
+	private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
+
 
 	@GetMapping("/get")
 	@SaCheckPermission("order:view")
-	public Result<SearchResult<OrderDonBackView>> get(Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle, Boolean isSubsidy) {
+	public Result<SearchResult<OrderDonBackView>> get(Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle, Boolean isSubsidy, Boolean isRenewPackage) {
 		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
 		if (channelId != null) {
 			List<Long> popularizeIds = channelPopularizeMapper.getPopularizeIdByChannelId(channelId);
@@ -167,6 +171,12 @@ public class CmsOrderController {
 			}
 			conditionSql += " exists (select 1 from order_don_subsidy_relate ocr where ocr.order_id = o.id limit 1)";
 		}
+		if (isRenewPackage != null) {
+			if (StrUtil.isNotEmpty(conditionSql)) {
+				conditionSql += " and ";
+			}
+			conditionSql += " exists (select 1 from order_don_renew_record odrr1 where odrr1.order_id = o.id limit 1)";
+		}
 		if (StrUtil.isNotBlank(conditionSql)) {
 			builder.put("condition", conditionSql);
 		}
@@ -1060,4 +1070,30 @@ public class CmsOrderController {
 				.build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
+
+	/**
+	 * 续费升级订单详情
+	 */
+	@GetMapping("/renew/orders/detail")
+	public Result<RenewOriOrderSkuDto> getRenewOrdersDetail(Long orderId) {
+		OrderDon orderDon = orderDonMapper.selectById(orderId);
+		if (orderDon.getOrderType() == 2) {
+			OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+					.eq(OrderDonRenewRecord::getOrderId, orderDon.getId())
+					.last("limit 1"));
+			if (orderDonRenewRecord != null) {
+				GroupsRelation relation = relationMapper.selectById(orderDon.getRelationId());
+				GoodsDonSku sku = skuMapper.selectById(orderDon.getSkuId());
+				Date expiryTime = relation.getExpiryTime();
+				DateTime lastExpiryTIme = DateUtil.offsetMonth(expiryTime, -sku.getMonths());
+
+				RenewOriOrderSkuDto renewOriOrderSkuDto = new RenewOriOrderSkuDto();
+				OriSkuDto oriSku = skuMapper.selectRenewOriSku(orderDonRenewRecord.getOriSkuId());
+				renewOriOrderSkuDto.setOriSku(oriSku);
+				renewOriOrderSkuDto.setLastExpiryTime(lastExpiryTIme);
+				return GatewayResponse.SUCCESS.newBuilder().toResult(renewOriOrderSkuDto);
+			}
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }

+ 26 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java

@@ -475,4 +475,30 @@ public class CmsUserController{
         Integer newConsumerCount = userMapper.getNewMaliceUser(beginOfDay);
         return GatewayResponse.SUCCESS.newBuilder().toResult(newConsumerCount > 0 ? true : false);
     }
+
+    /**
+     * 用户ip列表
+     */
+    @GetMapping("/get/ip/list")
+    public Result<SearchResult<OrderDonLocationRelateView>> orderDonLocationRelateResult(Long userId) {
+        if (userId == null) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        SearchResult<OrderDonLocationRelateView> search = beanSearcher.search(OrderDonLocationRelateView.class, MapUtils.flatBuilder(request.getParameterMap()).put("userId", String.format("where user_id in (%s)", userIdList.toString().replaceAll("\\[", "").replaceAll("]", ""))).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * 用户支付宝列表
+     */
+    @GetMapping("/get/zfb/list")
+    public Result<List<OrderDonBuyerView>> getZfbBuyers(Long userId) {
+        if (userId == null) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        List<OrderDonBuyerView> orderDonBuyerViews = beanSearcher.searchAll(OrderDonBuyerView.class, MapUtils.flatBuilder(request.getParameterMap()).field(OrderDonBuyerView::getUserId, userIdList).op(Operator.InList).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonBuyerViews);
+    }
 }

+ 20 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsGptCarController.java

@@ -2,6 +2,8 @@ package com.cyksj.web.controller.manage.account;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
@@ -112,6 +114,24 @@ public class CmsGptCarController {
 		chatgptSession.setIsCar(true);
 		chatgptSession.setOfficialSession(gptSession);
 		chatgptSessionMapper.insert(chatgptSession);
+		if(StringUtils.isBlank(chatgptSession.getCarId())){
+			JSONObject jsonObject = new JSONObject(gptSession);
+			String planType = jsonObject.getJSONObject("accountCheckInfo").getStr("plan_type");
+			if ("plus".equals(planType)) {
+				chatgptSession.setCarId("P" + chatgptSession.getId());
+				chatgptSession.setCarName("P" + chatgptSession.getId());
+			}else if("team".equals(planType)) {
+				chatgptSession.setCarId("T" + chatgptSession.getId());
+				chatgptSession.setCarName("T" + chatgptSession.getId());
+			}else {
+				chatgptSession.setCarId("P" + chatgptSession.getId());
+				chatgptSession.setCarName("P" + chatgptSession.getId());
+				chatgptSession.setIsPlus(0);
+			}
+			chatgptSessionMapper.updateById(chatgptSession);
+		}
+
+
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 }

+ 78 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/active/UserActivityController.java

@@ -1,8 +1,18 @@
 package com.cyksj.web.controller.manage.active;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserActivityRankRobotMapper;
+import com.cyksj.mapper.UserDistributeRankStatisticsRecordMapper;
 import com.cyksj.model.entity.UserActivity;
+import com.cyksj.model.entity.UserActivityRankRobot;
+import com.cyksj.model.views.ActivityOrderDataView;
+import com.cyksj.model.views.UserDistributeRankActivityView;
 import com.cyksj.service.user.UserActivityService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -13,8 +23,13 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.temporal.ChronoField;
+import java.util.List;
 
 /**
+ * admin/分销排行
  * 项目名: yhlxj
  * 文件名: UserActivityController
  * 创建者: JavaZou
@@ -31,6 +46,10 @@ public class UserActivityController {
 
 	private final HttpServletRequest request;
 
+	private final UserActivityRankRobotMapper rankRootMapper;
+
+	private final UserDistributeRankStatisticsRecordMapper userDistributeRankStatisticsRecordMapper;
+
 	/**
 	 * 新建活动
 	 */
@@ -66,9 +85,67 @@ public class UserActivityController {
 	 * 活动列表
 	 */
 	@GetMapping("/get")
-	public Result<SearchResult<UserActivity> > get() {
+	public Result<SearchResult<UserActivity>> get() {
 		SearchResult<UserActivity> search = beanSearcher.search(UserActivity.class, MapUtils.flatBuilder(request.getParameterMap()).field(UserActivity::getDeleted, 1).build());
+		search.getDataList().forEach(e -> {
+			if (e.getType() == 1) {
+				String statisticsTime;
+				if (e.getStatisticsType().equals(Constant.week)) {
+					statisticsTime = LocalDate.now().with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue()).toString();
+				} else {
+					statisticsTime = LocalDate.now().with(ChronoField.DAY_OF_MONTH, DayOfWeek.MONDAY.getValue()).toString();
+				}
+				List<UserActivityRankRobot> userActivityRankRobots = rankRootMapper.selectList(Wrappers.lambdaQuery(UserActivityRankRobot.class)
+						.eq(UserActivityRankRobot::getAcId, e.getId()));
+				userActivityRankRobots.forEach(robot -> {
+					UserActivityRankRobot moneyRank = userDistributeRankStatisticsRecordMapper.getRobotRankInfo(robot.getId(), Constant.money, statisticsTime);
+					if (moneyRank != null) {
+						robot.setMoney(moneyRank.getMoney());
+						robot.setMoneyRank(moneyRank.getRankId());
+					}
+					UserActivityRankRobot orderRank = userDistributeRankStatisticsRecordMapper.getRobotRankInfo(robot.getId(), Constant.orders, statisticsTime);
+					if (orderRank != null) {
+						robot.setOrders(orderRank.getOrders());
+						robot.setOrderRank(orderRank.getRankId());
+					}
+				});
+				e.setRankRobots(userActivityRankRobots);
+
+				try {
+					if (StrUtil.isNotBlank(e.getRewardInfo())) {
+						List<UserActivity.RewardInfo> rewardInfos = Jsons.parseList(e.getRewardInfo(), UserActivity.RewardInfo.class);
+						e.setRewardInfoList(rewardInfos);
+					}
+				} catch (Exception ex) {
+				}
+
+				//活动数据
+				ActivityOrderDataView activityOrderDataView = userDistributeRankStatisticsRecordMapper.selectAcOrderDataView(e.getId());
+				e.setOrderDataView(activityOrderDataView);
+			}
+		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 分销排行列表
+	 */
+	@GetMapping("/get/rank/list")
+	public Result<Page<UserDistributeRankActivityView>> rankList(Long acId, String nickname, Long userId, String date, @RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "10") Integer limit, @RequestParam(defaultValue = "0") Integer type, String orderBy, String sort) {
+		String field = Constant.money;
+		if (type == 1) {
+			field = Constant.orders;
+		}
+		UserActivity activity = userActivityService.getById(acId);
+		if (date == null) {
+			if (activity.getStatisticsType().equals(Constant.week)) {
+				date = LocalDate.now().with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue()).toString();
+			} else {
+				date = LocalDate.now().with(ChronoField.DAY_OF_MONTH, DayOfWeek.MONDAY.getValue()).toString();
+			}
+		}
+		Page<UserDistributeRankActivityView> page = userDistributeRankStatisticsRecordMapper.rankPage(nickname, userId, date, new Page<>(start, limit), field, orderBy, sort);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
+	}
+
 }

+ 4 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgAuditController.java

@@ -57,7 +57,7 @@ public class CorpMsgAuditController {
      * @return
      */
     @GetMapping
-    public Result<SearchResult<CorpMsgAuditUserView>> get(String textKey, @RequestParam(value = "tagIds", required = false) List<String> tagIds, Integer intention) throws Exception {
+    public Result<SearchResult<CorpMsgAuditUserView>> get(String textKey, @RequestParam(value = "tagIds", required = false) List<String> tagIds, Integer intention, Long talkStartTime, Long talkEndTime) throws Exception {
         Set<String> userIds = new HashSet<>();
         if(StringUtils.isNotBlank(textKey)){
             List<QyMsgContent> text = corpQyMsgContentService.list(Wrappers.lambdaQuery(QyMsgContent.class).select(QyMsgContent::getFrom, QyMsgContent::getExternalUserid,QyMsgContent::getTolist).like(QyMsgContent::getText, textKey).eq(QyMsgContent::getRoomid,"").eq(QyMsgContent::getMsgtype, "text"));
@@ -80,6 +80,9 @@ public class CorpMsgAuditController {
         if (intention != null) {
             builder.put("intention", String.format("and exists (select 1 from corp_user_pay_intention cup where cup.union_id = c.unionid and intention = %s limit 1)", intention));
         }
+        if (talkEndTime != null && talkStartTime != null) {
+            builder.put("talkTime", String.format(" and exists (select 1 from qy_msg_content qmc where qmc.external_userid = cu.external_userid and qmc.msgtime between %s and %s)", talkStartTime, talkEndTime));
+        }
         SearchResult<CorpMsgAuditUserView> search = beanSearcher.search(CorpMsgAuditUserView.class, builder.build());
         search.getDataList().forEach(e -> {
             Optional.ofNullable(corpUserPayIntentionMapper.selectOne(Wrappers.lambdaQuery(CorpUserPayIntention.class)

+ 9 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpTagController.java

@@ -206,4 +206,13 @@ public class CorpTagController {
 		Page<CorpTagUserOrderDataView> page = corpTagService.getTagUserTimeOrderData(start, limit, tagIdStr, toDate, startTime, endTime);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(page);
 	}
+
+	/**
+	 * 当日标签用户 本月下单情况
+	 */
+	@GetMapping("/get/fans/toMonth/orders")
+	public Result<UserOrderDetailView> getFansUserToMonthOrdersDetail(String tagId, String date) {
+		UserOrderDetailView userOrderDetailView = corpTagService.getFansUserToMonthOrdersDetail(tagId, date);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(userOrderDetailView);
+	}
 }

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -167,7 +167,7 @@ public class CouponController {
 	public Result<SearchResult<CouponDistributePopularizeView>> getRelationList(HttpServletRequest request) {
 		SearchResult<CouponDistributePopularizeView> search = beanSearcher.search(CouponDistributePopularizeView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
 		search.getDataList().forEach(data -> {
-			Integer usedNum = orderDonMapper.selectCouponCodeUserNum(data.getId(), Constant.noOrderAllStatus);
+			Integer usedNum = orderDonMapper.selectCouponCodeUserNum(data.getId(), data.getExCode(), Constant.noOrderAllStatus);
 			data.setUsedNum(usedNum);
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);

+ 11 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java

@@ -30,6 +30,7 @@ import com.cyksj.model.request.UserDistributeReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.distribute.UserDistributeReturnMoneyDetailService;
 import com.cyksj.service.mange.business.UserBusinessRateService;
 import com.cyksj.service.mange.statistics.StatisticsDataService;
 import com.cyksj.service.sys.SysConfigService;
@@ -125,13 +126,13 @@ public class DistributeController {
 
 	private final UserDistributeSubMapper userDistributeSubMapper;
 
+	private final UserDistributeReturnMoneyDetailService userDistributeReturnMoneyDetailService;
 	/**
 	 * 添加固定推广者
 	 */
 	@PostMapping
 	@SaCheckPermission("distribute:add")
 	@Log(module = "分销管理/增加推广者", businessType = BusinessType.POST, isSaveRequestData = true)
-	@Transactional(rollbackFor = Throwable.class)
 	public Result<String> saveDistributes(@RequestBody @NotNull UserDistributeReq userDistributeReq) {
 		try {
 			distributeService.insertDistribute(userDistributeReq);
@@ -142,11 +143,12 @@ public class DistributeController {
 			couponDistributePopularizeMapper.delete(Wrappers.lambdaQuery(CouponDistributePopularize.class)
 					.eq(CouponDistributePopularize::getUserId, userDistributeReq.getUserId())
 					.eq(CouponDistributePopularize::getIsGeneral, true));
-		} finally {
+		} catch (Exception e) {
 			String cacheKey = RedisService.key.USER_DISTRIBUTE_ADD_KEY.getNameFormat(userDistributeReq.getUserId());
 			if (redisService.hasKey(cacheKey)) {
 				redisService.del(cacheKey);
 			}
+			throw BusinessRuntimeException.getInstance(e.getMessage());
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult("添加成功");
 	}
@@ -164,6 +166,11 @@ public class DistributeController {
 		userDistributeMapper.deleteById(id);
 		userDistributeEquipmentMapper.delete(Wrappers.lambdaQuery(UserDistributeEquipment.class)
 				.eq(UserDistributeEquipment::getDistributeId, id));
+		//删除对应的优惠码关联
+		couponDistributePopularizeMapper.update(null, Wrappers.lambdaUpdate(CouponDistributePopularize.class)
+				.set(CouponDistributePopularize::getDeleted, 0)
+				.eq(CouponDistributePopularize::getDistributeId, id)
+				.eq(CouponDistributePopularize::getDeleted, 1));
 		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
 	}
 
@@ -491,6 +498,8 @@ public class DistributeController {
 			Long userId = distributeMoneyApply.getUserId();
 			userBenefitsService.addDistributePoints(userId, distributeMoneyApply.getPoints());
 			log.info("归还积分:{}至用户{}结束", distributeMoneyApply.getPoints(), userId);
+			//记录返现明细
+			userDistributeReturnMoneyDetailService.recordDistributeReturnMoney(distributeMoneyApply.getUserId(), distributeMoneyApply.getMoney(), "提现失败");
 		}
 		if (DistributeMoneyApply.Status.success.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
 //			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {

+ 132 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/renew/RenewUpgradePackageController.java

@@ -0,0 +1,132 @@
+package com.cyksj.web.controller.manage.renew;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.RenewUpgradePackage;
+import com.cyksj.model.views.RenewUpgradePackageView;
+import com.cyksj.service.mange.renew.RenewUpgradePackageService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RenewUpgradePackageController
+ * 创建者: JavaZou
+ * 创建时间:2024/7/18 16:59
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/manage/renew/upgrade")
+public class RenewUpgradePackageController {
+	private final RenewUpgradePackageService renewUpgradePackageService;
+
+	private final HttpServletRequest request;
+
+	private final BeanSearcher beanSearcher;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	/**
+	 * 新增套餐
+	 */
+	@PostMapping
+	@SaCheckPermission("upgrade:add")
+	@Log(module = "套餐管理/新增套餐", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> post(@RequestBody RenewUpgradePackage upgradePackage){
+		log.info("新增套餐:{}", upgradePackage);
+		renewUpgradePackageService.save(upgradePackage);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 修改套餐
+	 */
+	@PutMapping
+	@SaCheckPermission("upgrade:edit")
+	@Log(module = "套餐管理/修改套餐", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> put(@RequestBody RenewUpgradePackage upgradePackage){
+		log.info("修改套餐:{}", upgradePackage);
+		renewUpgradePackageService.updateById(upgradePackage);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除套餐
+	 */
+	@DeleteMapping("/{id}")
+	@SaCheckPermission("upgrade:delete")
+	@Log(module = "套餐管理/删除套餐", businessType = BusinessType.DELETE, isSaveRequestData = true)
+	public Result<String> delete(@PathVariable Long id){
+		log.info("删除套餐:{}", id);
+		RenewUpgradePackage byId = renewUpgradePackageService.getById(id);
+		if (byId == null){
+			throw BusinessRuntimeException.getInstance("套餐不存在");
+		}
+		byId.setDeleted(false);
+		renewUpgradePackageService.updateById(byId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 上下架套餐
+	 */
+	@PutMapping("/put/status/{id}")
+	@SaCheckPermission("upgrade:putStatus")
+	@Log(module = "套餐管理/上下架套餐", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<Boolean> putStatus(@PathVariable Long id){
+		log.info("上下架套餐:{}", id);
+		RenewUpgradePackage byId = renewUpgradePackageService.getById(id);
+		if (byId == null){
+			throw BusinessRuntimeException.getInstance("套餐不存在");
+		}
+		byId.setStatus(!byId.getStatus());
+		renewUpgradePackageService.updateById(byId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(byId.getStatus());
+	}
+
+	/**
+	 * 获取套餐
+	 */
+	@GetMapping("/{id}")
+	public Result<RenewUpgradePackage> get(@PathVariable Long id){
+		log.info("获取套餐:{}", id);
+		RenewUpgradePackage byId = renewUpgradePackageService.getById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(byId);
+	}
+
+	/**
+	 * 获取套餐列表
+	 */
+	@GetMapping
+	public Result<SearchResult<RenewUpgradePackageView>> list(Long skuId) {
+		log.info("获取套餐列表");
+		Map<String, Object> build = MapUtils.flatBuilder(request.getParameterMap()).build();
+		SearchResult<RenewUpgradePackageView> search = beanSearcher.search(RenewUpgradePackageView.class, build);
+		search.getDataList().forEach(upgradePackageView -> {
+			try {
+				String specVal = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class).in(GoodsDonSku::getId, Jsons.parseList(upgradePackageView.getUpgradeSkuIds(), Long.class))).stream().map(GoodsDonSku::getSpecVal).collect(Collectors.joining(","));
+				upgradePackageView.setUpgradeSpecVal(specVal);
+			} catch (Exception e) {
+				throw BusinessRuntimeException.getInstance("获取套餐规格失败");
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 36 - 389
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

@@ -1,47 +1,21 @@
 package com.cyksj.web.controller.mirror;
 
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
-import com.cyksj.common.util.IoKit;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.GroupsRelationMapper;
-import com.cyksj.mapper.MidjourneyPaintingPlazaMapper;
-import com.cyksj.mapper.MidjourneyUserMapper;
-import com.cyksj.model.dto.*;
-import com.cyksj.model.entity.GroupsRelation;
-import com.cyksj.model.entity.MidjourneyPaintingPlaza;
-import com.cyksj.model.entity.GroupsRelation;
-import com.cyksj.model.entity.MidjourneyPaintingPlaza;
 import com.cyksj.model.entity.MidjourneyUser;
-import com.cyksj.model.entity.MidjourneyUserConversation;
-import com.cyksj.model.response.SubmitResult;
-import com.cyksj.model.views.MidjourneyPaintingUserView;
-import com.cyksj.model.views.MidjourneyUserPaintingDayRecordView;
-import com.cyksj.model.views.MidjourneyUserPaintingRecordView;
-import com.cyksj.model.views.MidjourneyPaintingUserView;
-import com.cyksj.model.views.MidjourneyUserPaintingDayRecordView;
-import com.cyksj.model.views.MidjourneyUserPaintingRecordView;
-import com.cyksj.redis.RedisService;
-import com.cyksj.service.midjourney.MidjourneyAccountService;
+import com.cyksj.model.views.ChatgptCarInfoView;
+import com.cyksj.model.views.MidjourneyUserView;
 import com.cyksj.service.midjourney.MidjourneyService;
+import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
-import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
 
 /** server/镜像服务/mj绘画
  * @author zwhui
@@ -53,391 +27,64 @@ import java.util.Map;
 @RequestMapping("/applets/midjourney")
 public class MidjourneyController {
 
-    private final MidjourneyUserMapper midjourneyUserMapper;
 
     private final HttpServletRequest request;
 
     private final MidjourneyService midjourneyService;
 
     private final BeanSearcher beanSearcher;
-    
-    private final RedisService redisService;
 
-    private final GroupsRelationMapper groupsRelationMapper;
 
-    private final MidjourneyPaintingPlazaMapper midjourneyPaintingPlazaMapper;
-
-    public MidjourneyUser getUser(){
-        String userToken = request.getHeader("user-token");
-
-        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
-                .eq(MidjourneyUser::getUserToken, userToken).last("limit 1"));
-        if (midjourneyUser == null){
-            throw new BusinessRuntimeException("账号不存在,请重新登录");
-        }
-        if(!redisService.hasKey(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId())){
-            redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(),midjourneyUser.getMjFastNum());
-        }
-
-        if(!redisService.hasKey(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId())){
-            redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(),midjourneyUser.getMjRelaxNum());
-        }
-        Long relationId = midjourneyUser.getRelationId();
-        GroupsRelation relation = groupsRelationMapper.selectById(relationId);
-        midjourneyUser.setAqType(relation.getAqType());
-
-        return midjourneyUser;
-
-    }
-
-
-    /**
-     * 检查用户次数
-     */
-    public Long checkUserLimit(MidjourneyUser user){
-        Long num = 0L;
-        if (user.getExpireTime().before(new Date())){
-            throw BusinessRuntimeException.getInstance("账号已过期");
-        }
-       if (user.getMode() == 1){
-
-           num = redisService.decr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
-
-           if (num < 0) {
-               user.setMode(2);
-               midjourneyUserMapper.update(null, Wrappers.lambdaUpdate(MidjourneyUser.class).eq(MidjourneyUser::getId, user.getId()).set(MidjourneyUser::getMode, user.getMode()));
-               redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
-
-           }else {
-               int i = midjourneyUserMapper.decFastNum(user.getId(), 1, user.getMjFastNum());
-               if (i == 0) {
-                   redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + user.getId(), 1L);
-                   throw BusinessRuntimeException.getInstance("网络异常,请稍后再试");
-               }
-           }
-       }
-       if (user.getMode() == 2){
-           Object relax = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId());
-
-           if (relax != null){
-               num = redisService.decr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
-               if (num < 0){
-                   redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
-               }else {
-                   int i = midjourneyUserMapper.decRelaxNum(user.getId(), 1, user.getMjRelaxNum());
-                   if (i == 0) {
-                       redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + user.getId(), 1L);
-                       throw BusinessRuntimeException.getInstance("网络异常,请稍后再试");
-                   }
-               }
-           }else {
-               num = null;
-           }
-       }
-       return num;
-    }
-
-    /**
-     * 恢复次数
-     */
-    public void recoverUserLimit(Long id,Integer mode,Long num){
-        if (mode == 1){
-            redisService.incr(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + id, 1L);
-            midjourneyUserMapper.incrFastNum(id, 1);
-        }
-        if (mode == 2){
-            if (num != null){
-                redisService.incr(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + id, 1L);
-                midjourneyUserMapper.incrRelaxNum(id, 1);
-            }
-        }
-    }
-
-    ///**
-    // * 同步数据库
-    // */
-    //public void syncUser(Long id,Integer mode,Long num){
-    //    log.info("同步次数 id:{},mode:{},num:{}",id,mode,num);
-    //    if (num == null){
-    //        return;
-    //    }
-    //    LambdaUpdateWrapper<MidjourneyUser> wrapper = Wrappers.lambdaUpdate(MidjourneyUser.class)
-    //            .eq(MidjourneyUser::getId, id);
-    //    if (mode == 1){
-    //        wrapper.set(MidjourneyUser::getMjFastNum, num);
-    //    }
-    //    if (mode == 2){
-    //        wrapper.set(MidjourneyUser::getMjRelaxNum, num);
-    //    }
-    //    midjourneyUserMapper.update(null, wrapper);
-    //}
-
-
-    /**
-     * 查询用户信息
-     */
-    @GetMapping("/whoami")
-    public Result<MidjourneyUser> queryUser(){
-        MidjourneyUser user = getUser();
-        return GatewayResponse.SUCCESS.newBuilder().toResult(user);
-    }
-
-
-    /**
-     * 提交Imagine任务
-     */
-    @PostMapping("/submit/imagine")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> submitImagine(@RequestBody SubmitImagineDTO submitImagineDTO) {
-        log.info("提交Imagine任务,提示:{}",submitImagineDTO.getPrompt());
-        MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
-        }
-        MidjourneyUserConversation conversation;
-        try {
-            conversation = midjourneyService.submitImagine(user, submitImagineDTO.getPrompt(), submitImagineDTO.getBotType(), submitImagineDTO.getBase64Array());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
-        }
-        //syncUser(user.getId(), user.getMode(), num);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
-
-    /**
-     * 提交Describe任务
-     */
-    @PostMapping("/submit/describe")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> submitDescribe(@RequestBody SubmitDescribeDTO submitDescribeDTO) {
-        log.info("提交Describe任务");
-        MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
-        }
-        MidjourneyUserConversation conversation;
-        try {
-            conversation = midjourneyService.submitDescribe(user, submitDescribeDTO.getBotType(),submitDescribeDTO.getBase64());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
-        }
-        //syncUser(user.getId(), user.getMode(), num);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
-
-    /**
-     * 提交Blend任务
-     */
-    @PostMapping("/submit/blend")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> submitBlend(@RequestBody SubmitBlendDTO submitBlendDTO) {
-        log.info("提交Blend任务 dimensions:{},base64数组长度:{}", submitBlendDTO.getDimensions(), submitBlendDTO.getBase64Array().size());
-        MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
-        }
-        MidjourneyUserConversation conversation;
-        try {
-            conversation = midjourneyService.submitBlend(user, submitBlendDTO.getDimensions(), submitBlendDTO.getBotType(), submitBlendDTO.getBase64Array());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
-        }
-        //syncUser(user.getId(), user.getMode(), num);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
-
-    /**
-     * 提交Modal任务
-     */
-    @PostMapping("/submit/modal")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> submitModal(@RequestBody SubmitModalDTO submitModalDTO) {
-        log.info("提交Modal任务,taskId:{},提示:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt());
-        MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
-        }
-        MidjourneyUserConversation conversation;
-        try {
-            conversation = midjourneyService.submitModal(user, submitModalDTO.getTaskId(), submitModalDTO.getPrompt(), submitModalDTO.getMaskBase64());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
-        }
-        //syncUser(user.getId(), user.getMode(), num);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
-
-    /**
-     * 提交Shorten任务
-     */
-    @PostMapping("/submit/shorten")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> submitShorten(@RequestBody SubmitShortenDTO submitShortenDTO) {
-        log.info("提交Shorten任务 提示词:{}",submitShortenDTO.getPrompt());
-        MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
-        }
-        MidjourneyUserConversation conversation;
-        try {
-            conversation = midjourneyService.submitShorten(user, submitShortenDTO.getBotType(), submitShortenDTO.getPrompt());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
-        }
-        //syncUser(user.getId(), user.getMode(), num);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
+    //-------------------------alpha -----------------------
 
     /**
-     * 执行动作
+     * 获取车队列表
+     *
+     * @param relationId
+     * @return
      */
-    @PostMapping("/submit/action")
-    @NoSubmit
-    public Result<Object> action(@RequestBody SubmitActionDTO actionDTO) {
-        log.info("任务id:{},执行动作:{}",actionDTO.getTaskId(),actionDTO.getCustomId());
-        MidjourneyUser user = getUser();
-        Long num = 0L;
-        if (!actionDTO.getCustomId().contains("BOOKMARK")) {
-            num = checkUserLimit(user);
-            if (num != null && num < 0) {
-                throw BusinessRuntimeException.getInstance("次数已用完");
-            }
-        }
-        Object conversation;
-        try {
-            conversation = midjourneyService.submitAction(user, actionDTO.getTaskId(), actionDTO.getCustomId(),num, actionDTO.getBotType());
-        } catch (Exception e) {
-            recoverUserLimit(user.getId(), user.getMode(),num);
-            throw BusinessRuntimeException.getInstance(e.getMessage());
+    @GetMapping("/gpt/cars")
+    public Result<SearchResult<ChatgptCarInfoView>> getCarInfoList(Long relationId, @RequestParam(defaultValue = "true") Boolean isPlus) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        //查看用户是否存在车票
+        MidjourneyUser midjourneyUser = midjourneyService.getUser(userId, relationId);
+        if (midjourneyUser == null) {
+            throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
-        return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
-    }
-
-
-    /**
-     * 查询会话列表
-     */
-    @GetMapping("/conversation/list")
-    public Result<SearchResult<MidjourneyUserConversation>> conversationList(){
-        MidjourneyUser user = getUser();
-        log.info("查询会话列表 userId:{}",user.getId());
-        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(beanSearcher.search(MidjourneyUserConversation.class,
-                builder.field(MidjourneyUserConversation::getUserId, user.getId())
-                        .orderBy(MidjourneyUserConversation::getId).desc().build()));
-    }
+        SearchResult<ChatgptCarInfoView> carInfoList = beanSearcher.search(ChatgptCarInfoView.class,MapUtils.flatBuilder(request.getParameterMap()).build());
 
-    /**
-     * 根据ids查询会话
-     */
-    @GetMapping("/conversation/listByIds")
-    public Result<List<MidjourneyUserConversation>> conversationListByIds(Integer mode,@RequestParam(value = "ids" ) List<Long> ids) throws Exception {
-        MidjourneyUser user = getUser();
-        log.info("根据ids查询会话 userId:{}",user.getId());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.listConversationByIds(mode,ids));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
     }
 
     /**
-     * 取消任务
+     * 获取mj车票信息
      */
-    @PostMapping("/conversation/{id}/cancel")
-    @NoSubmit
-    public Result<MidjourneyUserConversation> conversationCancel(@PathVariable("id") Long id){
-        MidjourneyUser user = getUser();
-        log.info("取消任务 id:{}",id);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyService.cancelConversation(user,id));
-    }
-
-
-    /**
-     * 修改midjourney账号模式
-     */
-    @PutMapping("/put/midjourney/user/{mode}")
-    public Result<String> putMidjourneyUserMode(@PathVariable Integer mode, Long userId) {
-        log.info("修改midjourney账号模式 userId:{},mode:{}", userId, mode);
-        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectById(userId);
-        if (midjourneyUser == null) {
-            throw BusinessRuntimeException.getInstance("参数错误");
+    @GetMapping("/gpt/userInfo")
+    public Result<MidjourneyUserView> getUserInfo(Long relationId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(MidjourneyUserView::getUserId, userId).field(MidjourneyUserView::getRelationId, relationId)
+                .build());
+        if (search == null) {
+            throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
-        midjourneyUser.setMode(mode);
-        midjourneyUserMapper.updateById(midjourneyUser);
-        //redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken());
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
-
-    /**
-     * midjourney 回调
-     */
-    @PostMapping("/notifyHook")
-    public void notifyHook(HttpServletRequest request) throws Exception {
-        InputStream inputStream = request.getInputStream();
-        byte[] bytes = IoKit.toBytes(inputStream);
-        String json = new String(bytes, StandardCharsets.UTF_8);
-        midjourneyService.notifyHook(json);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
 
 
-    /**
-     * mj绘画广场
-     */
-    @GetMapping("/get/painting")
-    public Result<SearchResult<MidjourneyPaintingUserView>> getPaintingCollect() {
-        SearchResult<MidjourneyPaintingUserView> search = beanSearcher.search(MidjourneyPaintingUserView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .build());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
-    }
 
     /**
-     * 复制mj绘画广场 提示词
+     * 根据userToken GPT车队跳转登录
+     *
+     * @param carId 车队id
      */
-    @PostMapping("/painting/copy/{id}")
-    public Result<String> resetPaintingCopyNum(@PathVariable Long id) {
-        MidjourneyPaintingPlaza midjourneyPaintingPlaza = midjourneyPaintingPlazaMapper.selectById(id);
-        if (midjourneyPaintingPlaza != null) {
-            midjourneyPaintingPlazaMapper.updatePaintingCopyNum(id);
-        }
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    @GetMapping("/mirrorLogin/{relationId}/{carId}")
+    public Result<String> chatGPtCarLoginWithToken(@PathVariable Long relationId, @PathVariable String carId) {
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        midjourneyService.getUser(userId, relationId);
+        String url = midjourneyService.getCarLoginUrl(userId, relationId, carId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(url);
     }
 
-    /**
-     * 用户绘画记录
-     */
-    @GetMapping("/get/painting/record")
-    public Result<SearchResult<MidjourneyUserPaintingDayRecordView>> getPaintingRecord(String prompt, Boolean bookmark) {
-        MidjourneyUser user = getUser();
-        String condition = String.format(" and mc.user_id = %s", user.getId());
-        if (StrUtil.isNotBlank(prompt)) {
-            condition += String.format(" and mc.prompt like '%%%s%%'", prompt);
-        }
-        if (bookmark != null) {
-            condition += String.format(" and mc.bookmark is %s", bookmark);
-        }
-        SearchResult<MidjourneyUserPaintingDayRecordView> search = beanSearcher.search(MidjourneyUserPaintingDayRecordView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .put("condition", condition)
-                .orderBy(MidjourneyUserPaintingRecordView::getCreatedTime).desc()
-                .build());
-        String dateSql;
-        for (MidjourneyUserPaintingDayRecordView e : search.getDataList()) {
-            String date = e.getDate();
-            dateSql = String.format(" and DATE_FORMAT(mc.created_time,'%%Y-%%m-%%d') = '%s'", date);
-            List<MidjourneyUserPaintingRecordView> list = beanSearcher.searchAll(MidjourneyUserPaintingRecordView.class, MapUtils.builder()
-                    .put("condition", condition)
-                    .put("date", dateSql)
-                    .orderBy(MidjourneyUserPaintingRecordView::getCreatedTime).desc()
-                    .build());
-            e.setList(list);
-        }
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
-    }
 }

+ 73 - 23
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -1,14 +1,17 @@
 package com.cyksj.web.controller.mirror;
 
 import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.model.entity.ChatgptSession;
-import com.cyksj.model.entity.ChatgptUser;
-import com.cyksj.model.entity.MidjourneyUser;
+import com.cyksj.mapper.GroupsMapper;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.renew.RenewUpgradePackageMapper;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.request.gpt.ConversationRequest;
 import com.cyksj.model.response.ConversationLimitResponse;
 import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
@@ -31,13 +34,14 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.swing.text.html.Option;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
-import java.util.Set;
+import java.util.Optional;
 
 /**
  * /server/镜像服务
@@ -71,6 +75,12 @@ public class MirrorController {
     @Value("${midjourney.drawUrl}")
     private String midjourneyDrawUrl;
 
+    private final RenewUpgradePackageMapper renewUpgradePackageMapper;
+
+    private final GroupsRelationMapper relationMapper;
+
+    private final GroupsMapper groupsMapper;
+
 
     /**
      * GPT车票跳转登录
@@ -102,7 +112,8 @@ public class MirrorController {
             ChatgptSession session = chatGptAccountService.checkSession(carId);
             if (session.getIsCar()) {
                 log.info("用户:{}通过userToken:{}访问镜像车队carId:{}成功", user.getName(), userToken, carId);
-                return GatewayResponse.SUCCESS.newBuilder().setMsg("登陆成功").setCode(1).toResult();
+
+                return GatewayResponse.SUCCESS.newBuilder().setMsg("登陆成功").setCode(1).toResult(StringUtil.getString(user.getRelationId()));
             }
         } catch (Exception e) {
             log.error("服务器错误", e);
@@ -152,29 +163,43 @@ public class MirrorController {
         ChatgptUser user = chatGptAccountService.findByUserTokenAndExpireTimeAfter(userToken, LocalDateTime.now());
         //3.如果记录不存在,返回状态码 401
         if (user == null) {
-            response.setStatus(401);
-        }
-        if (StringUtils.isNotBlank(conversationRequest.getCarId())) {
-            //4.获取gpt-4 的规则限制
-            //text-davinci-002-render-sha 3.5
-            ConversationLimitResponse conversationLimitResponse = chatGptAccountService.conversationLimit(userToken, conversationRequest.getModel(), conversationRequest.getCarId(), user, isCar);
-
-            if (conversationLimitResponse.isLimited()) {
+            response.setStatus(400);
+            ChatgptConversionLimitView chatgptConversionLimitView = new ChatgptConversionLimitView();
+            ChatgptConversionLimitView.Detail detail = new ChatgptConversionLimitView.Detail();
+            detail.setMessage("看来您还没车票呢,是不是还没登录呀,赶紧去车票内重新选择上车 \uD83D\uDE97 [点击直达](https://nf.video/ticket)");
+            chatgptConversionLimitView.setDetail(detail);
+            return chatgptConversionLimitView;
+        }else {
+            if (user.getIsBlock() != null && user.getIsBlock()) {
                 response.setStatus(400);
-                //String json = "{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型,或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
                 ChatgptConversionLimitView chatgptConversionLimitView = new ChatgptConversionLimitView();
                 ChatgptConversionLimitView.Detail detail = new ChatgptConversionLimitView.Detail();
-                String url = "[点击此处升级](https://nf.video/ticket?relationId=%d&pType=pay)";
-
-                String format = String.format(url, user.getRelationId());
-                detail.setMessage("您目前的套餐已达到GPT-4的使用上限。您可以继续使用3.5,预计 " + DateUtil.format(new Date(conversationLimitResponse.getNextAvailableTime()), "yyyy-MM-dd HH:mm:ss") + " 恢复" + ",如需增加滚动时间内可询问次数," + format);
+                detail.setMessage("抱歉,您因违反银河录像局使用条款已被封禁.");
                 chatgptConversionLimitView.setDetail(detail);
                 return chatgptConversionLimitView;
-            } else {
-                response.setStatus(200);
             }
-            //5.获取 conversationRequest 中的model 字段,判断是否为 gpt-4 如果为gpt-4 执行 查看是否达到限制方法
-            //6.如果达到限制,返回状态码 429 并返回文本 xxx
+            if (StringUtils.isNotBlank(conversationRequest.getCarId())) {
+                //4.获取gpt-4 的规则限制
+                //text-davinci-002-render-sha 3.5
+                ConversationLimitResponse conversationLimitResponse = chatGptAccountService.conversationLimit(userToken, conversationRequest.getModel(), conversationRequest.getCarId(), user, isCar);
+
+                if (conversationLimitResponse.isLimited()) {
+                    response.setStatus(400);
+                    //String json = "{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型,或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
+                    ChatgptConversionLimitView chatgptConversionLimitView = new ChatgptConversionLimitView();
+                    ChatgptConversionLimitView.Detail detail = new ChatgptConversionLimitView.Detail();
+                    String url = "[点击此处升级](https://nf.video/ticket?relationId=%d&pType=pay)";
+
+                    String format = String.format(url, user.getRelationId());
+                    detail.setMessage("您目前的套餐已达到GPT-4的使用上限。您可以继续使用3.5或4o-mini,预计 " + DateUtil.format(new Date(conversationLimitResponse.getNextAvailableTime()), "yyyy-MM-dd HH:mm:ss") + " 恢复" + ",如需增加滚动时间内可询问次数," + format);
+                    chatgptConversionLimitView.setDetail(detail);
+                    return chatgptConversionLimitView;
+                } else {
+                    response.setStatus(200);
+                }
+                //5.获取 conversationRequest 中的model 字段,判断是否为 gpt-4 如果为gpt-4 执行 查看是否达到限制方法
+                //6.如果达到限制,返回状态码 429 并返回文本 xxx
+            }
         }
 
         return new ChatgptConversionLimitView();
@@ -344,7 +369,7 @@ public class MirrorController {
     public Result<String> midjourneyMirror(@PathVariable Long relationId) {
         Long userId = StpUserUtil.getLoginIdAsLong();
         MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(userId, relationId);
-        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyHost + (EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8081":"/8082") +"/api/applets/mirror/midjourneyMirrorWithToken/" + midjourneyUser.getUserToken());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(midjourneyHost + (EnvCommonService.active.equals(envCommonService.getEnv()) ? "/8081":"/8082") +"/api/applets/midjourney/midjourneyMirrorWithToken/" + midjourneyUser.getUserToken());
     }
 
     @GetMapping("/midjourneyMirrorWithToken/{userToken}")
@@ -355,4 +380,29 @@ public class MirrorController {
         response.addCookie(cookie);
         response.sendRedirect(midjourneyDrawUrl);
     }
+
+    /**
+     * gpt续费广告弹窗
+     */
+    @GetMapping("/get/gpt/renew/discount")
+    public Result<RenewUpgradePackage> getGptRenewDiscount(Long relationId) {
+        if (relationId != null) {
+            GroupsRelation relation = relationMapper.selectById(relationId);
+            if (relation != null) {
+                GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+                if (groupsTrips != null) {
+                    RenewUpgradePackage renewUpgradePackage = renewUpgradePackageMapper.selectOne(Wrappers.lambdaQuery(RenewUpgradePackage.class)
+                            .eq(RenewUpgradePackage::getGoodsId, 18)
+                            .eq(RenewUpgradePackage::getStatus, 1)
+                            .eq(RenewUpgradePackage::getDeleted, 1)
+                            .eq(RenewUpgradePackage::getSkuId, groupsTrips.getSkuId())
+                            .orderByAsc(RenewUpgradePackage::getDiscount)
+                            .last("limit 1")
+                            .select(RenewUpgradePackage::getId, RenewUpgradePackage::getDiscount));
+                    return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackage);
+                }
+            }
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
 }

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

@@ -20,6 +20,7 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.OrderDonRenewRecordMapper;
 import com.cyksj.mapper.OrderDonWaybillMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
@@ -68,10 +69,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -128,6 +126,9 @@ public class OrderController {
     @Autowired
     private GoodsDonSkuMapper skuMapper;
 
+    @Autowired
+    private OrderDonRenewRecordMapper orderDonRenewRecordMapper;
+
     /**
      * 支付
      * @author chan
@@ -143,7 +144,7 @@ public class OrderController {
         String ip = ServletUtil.getClientIP(request);
         String address = StringUtil.getNewInternalAddressByIp(ip);
         //address.contains("柬埔寨") ||
-        if (address.contains("缅甸")) {
+        if (address == null || address.contains("缅甸")) {
             throw BusinessRuntimeException.getInstance("用户系统异常");
         }
         payRequest.setIp(ip);
@@ -477,7 +478,15 @@ public class OrderController {
                     }
                 }
             }
-            data.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId, data.getId()).last("limit 1")));
+            if (data.getRelationId() == 0) {
+                data.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId, data.getId()).last("limit 1")));
+            }
+            if (data.getOrderType() == 2) {
+                OrderDonRenewRecord orderDonRenewRecord = orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+                        .eq(OrderDonRenewRecord::getOrderId, data.getId())
+                        .last("limit 1"));
+                data.setIsRenewPackage(orderDonRenewRecord != null ? true : false);
+            }
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
@@ -516,6 +525,15 @@ public class OrderController {
         if (orderDonView == null) {
             throw BusinessRuntimeException.getInstance("订单不存在");
         }
+        if (orderDonView.getIsMirror() && orderDonView.getOrderType() == 2) {
+            Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
+                            .eq(OrderDonRenewRecord::getOrderId, orderId)
+                            .last("limit 1")))
+                    .ifPresent(renew -> {
+                        GoodsDonSku sku = skuMapper.selectById(renew.getOriSkuId());
+                        orderDonView.setOriSpecVal(sku.getSpecVal());
+                    });
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonView);
     }
 
@@ -809,4 +827,39 @@ public class OrderController {
         }
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
+
+    /**
+     * 续费升级提交支付
+     */
+    @PostMapping("/post/renew/upgrade/submit")
+    public Result<OrderDon> submitRenewUpgrade(@Validated @RequestBody OrderPayRequest payRequest) throws Exception {
+        final String methodName = "续费升级吊起支付";
+        //无需免登录
+        Long userId = StpUserUtil.getLoginIdAsLong();
+        payRequest.setUserId(userId);
+        log.info("{}[start] params:{}", methodName, payRequest);
+
+        String ip = ServletUtil.getClientIP(request);
+
+        payRequest.setIp(ip);
+
+        OrderDon orderDon = orderDonService.submitRenewUpgrade(payRequest);
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
+    }
+
+    /**
+     * 获取续费套餐订单列表
+     */
+    @GetMapping("/renew/get")
+    public Result<SearchResult<RenewUpgradeOrderDonView>> listRenewOrders(){
+        long userId = StpUserUtil.getLoginIdAsLong();
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        List<Long> userIds = UserBindRelationService.getRelationUserIdList(userId, null);
+        SearchResult<RenewUpgradeOrderDonView> search = beanSearcher.search(RenewUpgradeOrderDonView.class, builder
+                .field(UpgradeOrderDonView::getUserId, userIds).op(Operator.InList)
+                .orderBy(UpgradeOrderDonView::getId).desc()
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 }