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

Merge branch 'pre' into distribute_general_rank

zoujiajian 2 лет назад
Родитель
Сommit
5a0ee1d6a8
71 измененных файлов с 2129 добавлено и 673 удалено
  1. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsDonSkuMapper.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyPaintingCollectRecordMapper.java
  3. 14 0
      netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserMapper.java
  4. 19 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonRenewRecordMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/renew/RenewUpgradePackageMapper.java
  6. 1 1
      netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopGoodsSkuMapper.java
  7. 18 0
      netflix-dao/src/main/java/com/cyksj/model/dto/OriSkuDto.java
  8. 21 0
      netflix-dao/src/main/java/com/cyksj/model/dto/RenewOriOrderSkuDto.java
  9. 8 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitActionDTO.java
  10. 8 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitBlendDTO.java
  11. 8 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitDescribeDTO.java
  12. 9 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitImagineDTO.java
  13. 8 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SubmitShortenDTO.java
  14. 25 1
      netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptUser.java
  15. 5 5
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java
  16. 27 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyPaintingCollectRecord.java
  17. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUserConversation.java
  18. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  19. 31 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonRenewRecord.java
  20. 53 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RenewUpgradePackage.java
  21. 4 4
      netflix-dao/src/main/java/com/cyksj/model/entity/ShopConfig.java
  22. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributeSubRewards.java
  23. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java
  24. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonSearchView.java
  25. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  26. 79 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/RenewUpgradeOrderDonView.java
  27. 1 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonBackView.java
  28. 0 5
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonView.java
  29. 1 0
      netflix-dao/src/main/java/com/cyksj/model/response/SubmitResult.java
  30. 5 0
      netflix-dao/src/main/java/com/cyksj/model/views/ChatGptUserView.java
  31. 67 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageFrontView.java
  32. 91 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewUpgradePackageView.java
  33. 12 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  34. 7 0
      netflix-dao/src/main/resources/mapper/GoodsDonSkuMapper.xml
  35. 19 0
      netflix-dao/src/main/resources/mapper/OrderDonRenewRecordMapper.xml
  36. 12 7
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  37. 1 3
      netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java
  38. 1 1
      netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardGoodsSkuServiceImpl.java
  39. 8 0
      netflix-service/src/main/java/com/cyksj/service/mange/MirrorUserCleatService.java
  40. 51 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  41. 92 4
      netflix-service/src/main/java/com/cyksj/service/mange/impl/MirrorUserCleatServiceImpl.java
  42. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/renew/RenewUpgradePackageService.java
  43. 19 0
      netflix-service/src/main/java/com/cyksj/service/mange/renew/impl/RenewUpgradePackageServiceImpl.java
  44. 9 5
      netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java
  45. 270 78
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java
  46. 2 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  47. 152 32
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  48. 3 3
      netflix-service/src/main/java/com/cyksj/service/pay/impl/TransferFuncServiceImpl.java
  49. 27 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  50. 13 13
      netflix-service/src/main/java/com/cyksj/service/scheduler/SchedulerService.java
  51. 272 272
      netflix-service/src/main/java/com/cyksj/service/scheduler/impl/SchedulerServiceImpl.java
  52. 1 1
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java
  53. 1 1
      netflix-service/src/main/java/com/cyksj/service/sys/impl/SysFuncTimingShelfServiceImpl.java
  54. 2 2
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserIdentCertServiceImpl.java
  55. 83 83
      netflix-service/src/main/java/com/cyksj/task/CorpChatScheduler.java
  56. 4 16
      netflix-web/src/main/java/com/cyksj/web/controller/cps/CpsBackLoginController.java
  57. 19 19
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  58. 66 1
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  59. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/information/InformationController.java
  60. 37 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  61. 3 3
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java
  62. 1 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/home/HomeManageConfigController.java
  63. 132 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/renew/RenewUpgradePackageController.java
  64. 102 73
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java
  65. 68 22
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java
  66. 58 5
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  67. 2 2
      netflix-web/src/main/java/com/cyksj/web/controller/sys/SysConfigController.java
  68. 0 0
      netflix-web/src/main/resources/application-dev.yml
  69. 0 0
      netflix-web/src/main/resources/application-prd.yml
  70. 3 2
      netflix-web/src/main/resources/application-pre.yml
  71. 1 2
      netflix-web/src/main/resources/application.yml

+ 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);
 }

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

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

+ 14 - 0
netflix-dao/src/main/java/com/cyksj/mapper/MidjourneyUserMapper.java

@@ -2,10 +2,24 @@ package com.cyksj.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.MidjourneyUser;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
 
 /**
  * @author zwhui
  * @date 2024/4/16 17:46
  */
 public interface MidjourneyUserMapper extends BaseMapper<MidjourneyUser> {
+
+    @Update("update midjourney_user set mj_fast_num = mj_fast_num + #{num} where id = #{id}")
+    int incrFastNum(@Param("id") Long id, @Param("num") Integer num);
+
+    @Update("update midjourney_user set mj_fast_num = mj_fast_num - #{num} where id = #{id} and mj_fast_num = #{mjFastNum} and mj_fast_num > 0")
+    int decFastNum(@Param("id") Long id, @Param("num") Integer num, @Param("mjFastNum") Integer mjFastNum);
+
+    @Update("update midjourney_user set mj_relax_num = mj_relax_num + #{num} where id = #{id}")
+    int incrRelaxNum(@Param("id") Long id, @Param("num") Integer num);
+
+    @Update("update midjourney_user set mj_relax_num = mj_relax_num - #{num} where id = #{id} and mj_relax_num = #{relaxNum} and mj_relax_num > 0")
+    int decRelaxNum(@Param("id") Long id, @Param("num") Integer num, @Param("relaxNum") Integer relaxNum);
 }

+ 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/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")

+ 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;
+
+}

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitActionDTO.java

@@ -22,4 +22,12 @@ public class SubmitActionDTO {
      */
     @NotNull(message = "任务ID不能为空")
     private Long taskId;
+
+    /**
+     * 机器人类型
+     * bot类型,mj(默认)或niji,可用值:MID_JOURNEY,NIJI_JOURNEY,示例值(MID_JOURNEY)
+     * MID_JOURNEY
+     * NIJI_JOURNEY
+     */
+    private String botType = "MID_JOURNEY";
 }

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitBlendDTO.java

@@ -22,4 +22,12 @@ public class SubmitBlendDTO {
 	 * 比例: PORTRAIT(2:3); SQUARE(1:1); LANDSCAPE(3:2)
 	 */
 	private BlendDimensions dimensions = BlendDimensions.SQUARE;
+
+	/**
+	 * 机器人类型
+	 * bot类型,mj(默认)或niji,可用值:MID_JOURNEY,NIJI_JOURNEY,示例值(MID_JOURNEY)
+	 * MID_JOURNEY
+	 * NIJI_JOURNEY
+	 */
+	private String botType = "MID_JOURNEY";
 }

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitDescribeDTO.java

@@ -16,4 +16,12 @@ public class SubmitDescribeDTO {
 	 */
 	@NotBlank(message = "请上传图片")
 	private String base64;
+
+	/**
+	 * 机器人类型
+	 * bot类型,mj(默认)或niji,可用值:MID_JOURNEY,NIJI_JOURNEY,示例值(MID_JOURNEY)
+	 * MID_JOURNEY
+	 * NIJI_JOURNEY
+	 */
+	private String botType = "MID_JOURNEY";
 }

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitImagineDTO.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.dto;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
 
 import javax.validation.constraints.NotBlank;
@@ -23,4 +24,12 @@ public class SubmitImagineDTO {
      */
     private List<String> base64Array;
 
+    /**
+     * 机器人类型
+     * bot类型,mj(默认)或niji,可用值:MID_JOURNEY,NIJI_JOURNEY,示例值(MID_JOURNEY)
+     * MID_JOURNEY
+     * NIJI_JOURNEY
+     */
+    private String botType = "MID_JOURNEY";
+
 }

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SubmitShortenDTO.java

@@ -16,4 +16,12 @@ public class SubmitShortenDTO {
      */
     @NotBlank(message = "提示词不能为空")
     private String prompt;
+
+    /**
+     * 机器人类型
+     * bot类型,mj(默认)或niji,可用值:MID_JOURNEY,NIJI_JOURNEY,示例值(MID_JOURNEY)
+     * MID_JOURNEY
+     * NIJI_JOURNEY
+     */
+    private String botType = "MID_JOURNEY";
 }

+ 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;
+}

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

@@ -74,6 +74,11 @@ public class GroupsRelation extends BaseEntity {
 
     private Long yhsId;
 
+    /**
+     * 车票获取类型 默认1购买,2.体验
+     */
+    private Integer aqType;
+
     /**
      * 获取权益时的订单id
      */
@@ -103,11 +108,6 @@ public class GroupsRelation extends BaseEntity {
     @DbIgnore
     private Integer maxNum;
 
-    /**
-     * 车票获取类型 默认1购买,2.体验
-     */
-    private Integer aqType;
-
 
     @AllArgsConstructor
     @Getter

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyPaintingCollectRecord.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.entity;
+
+import com.cyksj.model.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: MidjourneyPaintingCollectRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/6/3 17:18
+ */
+@Getter
+@Setter
+public class MidjourneyPaintingCollectRecord extends BaseEntity {
+	private Long userId;
+
+	/**
+	 * 绘画id
+	 */
+	private Long plazaId;
+
+	/**
+	 * 收藏状态
+	 */
+	private Boolean status;
+}

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

@@ -42,6 +42,12 @@ public class MidjourneyUserConversation extends BaseEntity implements Serializab
      */
     private Integer mode;
 
+    /**
+     *  MID_JOURNEY
+     *  NIJI_JOURNEY
+     */
+    private String BotType;
+
     /**
      * 开始时间
      */

+ 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;
+}

+ 4 - 4
netflix-dao/src/main/java/com/cyksj/model/entity/ShopConfig.java

@@ -14,15 +14,15 @@ import lombok.Setter;
 public class ShopConfig extends BaseEntity{
 
     /**
-     * 木棉支付宝商户
+     * 善意支付宝商户
      */
-    public static final String ZFB_DEFAULT_APP_ID = "2021003171697073";
+    public static final String ZFB_DEFAULT_APP_ID = "2021004146676727";
 
     /**
-     * 分销提现支付宝默认商户
+     * 分销提现支付宝默认商户 善意
      *
      */
-    public static final String DISTRIBUTE_ZFB_DEFAULT_APP_ID = "2021003171697073";
+    public static final String DISTRIBUTE_ZFB_DEFAULT_APP_ID = "2021004146676727";
 
     public static final String WX_DEFAULT_APP_ID = "1634772026";
 

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

@@ -14,7 +14,7 @@ import java.math.BigDecimal;
  */
 @Getter
 @Setter
-public class UserDistributeSubRewards {
+public class UserDistributeSubRewards extends BaseEntity{
 	private Integer level;
 
 	/**

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

@@ -284,4 +284,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

+ 1 - 0
netflix-dao/src/main/java/com/cyksj/model/response/SubmitResult.java

@@ -22,6 +22,7 @@ public class SubmitResult {
      */
     private String result;
 
+    private Long instanceId;
     /**
      * 扩展字段
      */

+ 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;
 }

+ 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;
 }

+ 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>

+ 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>

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

@@ -1,5 +1,6 @@
 package com.cyksj.redis;
 
+import com.cyksj.common.constant.RandomConstant;
 import com.cyksj.common.util.StringUtil;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -115,7 +116,7 @@ public class RedisService {
      * @return 值
      */
     public String getStr(String key) {
-            return key == null ? null : StringUtil.getString(redisTemplate.opsForValue().get(key));
+        return key == null ? null : StringUtil.getString(redisTemplate.opsForValue().get(key));
     }
 
     /**
@@ -213,7 +214,7 @@ public class RedisService {
      * @param map 对应多个键值
      * @return true 成功 false 失败
      */
-    public Boolean hmset(String key, Map<String, Object> map) {
+    public Boolean hmset(String key, Map<Object, Object> map) {
         try {
             redisTemplate.opsForHash().putAll(key, map);
             return true;
@@ -747,9 +748,9 @@ public class RedisService {
     @Getter
     public enum key {
 
-	    CORP_AUTH_MAPPING_KEY("mapping:corp:", "企业微信授权跳转", 60 * 60 * 24L),
-	    CORP_ACCESSO_TOKEN_KEY("corp:access_token:", "corp_access_token", 60 * 30L),
-	    MAPPING_INDEX_KEY("mapper:index:", "授权跳转", 60 * 10L),
+        CORP_AUTH_MAPPING_KEY("mapping:corp:", "企业微信授权跳转", 60 * 60 * 24L),
+        CORP_ACCESSO_TOKEN_KEY("corp:access_token:", "corp_access_token", 60 * 30L),
+        MAPPING_INDEX_KEY("mapper:index:", "授权跳转", 60 * 10L),
         WX_LOGIN_AUTH_URI("wx_login_auth_uri:%s:%s", "微信网页授权登录uri", 60 * 60 * 24L),
         RECOMMEND_COUPON_DAY("recommend_coupon_day:%s", "推荐优惠券弹窗", 60 * 60 * 24L),
         EMAIL_CODE_KEY("email_code_key:%s", "邮箱验证码", 60 * 3),
@@ -835,12 +836,16 @@ public class RedisService {
         CHATGPT_CAR_LOW_CHAT("chatgpt:car:low:chat:","chatGpt 3.5 对话次数", 48 * 60 * 60L),
         //车票到期前每日通知key
         TICKET_EXPIRY_NOTIFY_DAY("ticket_expiry_notify_day:%s:%s", "车票到期前每日通知key", 60 * 60 * 24L),
-        MIDJOURNEY_FAST_LIMIT("midjourney:fast:limit:", "midjourney fast次数", 60 * 60 * 48L),
-        MIDJOURNEY_RELAX_LIMIT("midjourney:relax:limit:", "midjourney relax次数", 60 * 60 * 48L),
+        MIDJOURNEY_FAST_LIMIT("midjourney:fast:limit:", "midjourney fast次数", 60 * 60 * 24L * 7),
+        MIDJOURNEY_RELAX_LIMIT("midjourney:relax:limit:", "midjourney relax次数", 60 * 60 * 24L * 7),
         MIDJOURNEY_EXPIRE_TIME("midjourney:expire:time:", "midjourney expire time", 60 * 60 * 48L),
         MIDJOURNEY_USER("midjourney:user:", "midjourney user", 60 * 60 * 2L),
+        MIDJOURNEY_CONVERSATION("midjourney:conversation:", "midjourney conversation", 60 * 60 * 2L),
         MIDJOURNEY_ACCOUNT("midjourney:account:", "midjourney account", 60 * 60 * 48L),
+        MIDJOURNEY_QUERY("midjourney:query:", "midjourney query", 60 * 60 * 2L),
         APPLY_MONEY_DAY_LIMIT_KEY("apply_money_day_limit_key:%s:%s:%s", "每日提现次数限制", 60 * 60 * 24L),
+        MIDJOURNEY_RELAX_CONVERSATION("midjourney:relax:conversation:", "midjourney relax conversation", 60 * 60 * 2L),
+        MIDJOURNEY_ACCOUNT_USED("midjourney:account:used:", "midjourney account used", 60 * 60 * 48L),
         NETFLIX_SET_LIMIT_TIME("netflix_set_limit_time", "奈飞设置限制", 30l),
         ;
 

+ 1 - 3
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;
@@ -850,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("您还未购买该车票");

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardGoodsSkuServiceImpl.java

@@ -118,7 +118,7 @@ public class GiftCardGoodsSkuServiceImpl extends ServiceImpl<GiftCardGoodsSkuMap
 			if (minPrice == null || min.getPrice().compareTo(minPrice) != 0) {
 				goodsDon.setMinPrice(min.getPrice());
 				goodsDonMapper.updateById(goodsDon);
-				Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "*");
+				Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "*");
 				redisService.del(keys.toArray(String[]::new));
 			}
 		}

+ 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);
 }

+ 51 - 0
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);
     }
 
     /**
@@ -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 {
+}

+ 9 - 5
netflix-service/src/main/java/com/cyksj/service/midjourney/MidjourneyService.java

@@ -3,27 +3,31 @@ 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, List<String> base64Array) throws Exception;
+    MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt, String botType,  List<String> base64Array) throws Exception;
 
-    MidjourneyUserConversation submitDescribe(MidjourneyUser user, String base64) throws Exception;
+    MidjourneyUserConversation submitDescribe(MidjourneyUser user, String botType, String base64) throws Exception;
 
-    MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, List<String> base64Array) throws Exception;
+    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 prompt) throws Exception;
+    MidjourneyUserConversation submitShorten(MidjourneyUser user, String botType, String prompt) throws Exception;
 
     List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) throws Exception;
 
-    MidjourneyUserConversation submitAction(MidjourneyUser user, Long taskId, String customId) 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;
 }

+ 270 - 78
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidjourneyServiceImpl.java

@@ -1,31 +1,40 @@
 package com.cyksj.service.midjourney.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.map.MapUtil;
 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.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.response.SubmitResult;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.service.midjourney.MidjourneyService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.imageio.stream.FileImageOutputStream;
-import java.io.IOException;
+import java.io.*;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.*;
@@ -52,97 +61,153 @@ public class MidjourneyServiceImpl implements MidjourneyService {
 
     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 static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
+    private final MidjourneyAccountService midjourneyAccountService;
+
 
     @Override
-    public MidjourneyUserConversation submitImagine(MidjourneyUser user, String prompt, List<String> base64Array) throws Exception {
+    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();
+                .put("prompt", prompt)
+                .put("state", user.getId())
+                .build();
         if (CollectionUtil.isNotEmpty(base64Array)) {
             imagineParam.put("base64Array", base64Array);
         }
-        SubmitResult result = submit(user.getMode(),"imagine", imagineParam);
-        return saveConversation(user.getId(), user.getMode(),Long.parseLong(result.getResult()),result.getProperties(),"IMAGINE", StringUtils.EMPTY);
+        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);
     }
 
-    public MidjourneyUserConversation saveConversation(Long userId,Integer mode,Long taskId,Map<String,Object> properties, String action,String prompt) throws Exception {
+    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("IN_PROGRESS").setTaskId(taskId);
+                .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;
     }
 
 
     @Override
-    public MidjourneyUserConversation submitDescribe(MidjourneyUser user, 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", param);
-        return saveConversation(user.getId(), user.getMode(),Long.parseLong(result.getResult()),result.getProperties(),"DESCRIBE", StringUtils.EMPTY);
+    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);
     }
 
     @Override
-    public MidjourneyUserConversation submitBlend(MidjourneyUser user, BlendDimensions dimensions, List<String> base64Array) throws Exception {
+    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();
+                .put("base64Array", base64Array)
+                .put("state", user.getId())
+                .build();
         if (dimensions != null) {
             param.put("dimensions", dimensions);
         }
-        SubmitResult result = submit(user.getMode(),"blend", param);
-        Map<String, Object> properties = result.getProperties();
-        if (user.getMode() == 1) {
-            String finalPrompt = "%s --ar %s --style raw --s 250";
-            List<String> picList = uploadBase64Pic(base64Array);
-            String pics = picList.stream().map(pic -> "<" + pic + ">").collect(Collectors.joining(" "));
-            properties.put("finalPrompt", String.format(finalPrompt, pics,dimensions.getValue()));
+        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(), Long.parseLong(result.getResult()),properties,"BLEND", StringUtils.EMPTY);
+        return saveConversation(user.getId(), user.getMode(),result,"BLEND", StringUtils.EMPTY, botType);
     }
 
     @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();
+                .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", param);
-        return saveConversation(user.getId(),  user.getMode(),Long.parseLong(result.getResult()),result.getProperties(),"MODAL", StringUtils.EMPTY);
+        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);
     }
 
     @Override
-    public MidjourneyUserConversation submitShorten(MidjourneyUser user, String prompt) throws Exception {
+    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", param);
-        return saveConversation(user.getId(), user.getMode(), Long.parseLong(result.getResult()),result.getProperties(),"SHORTEN", StringUtils.EMPTY);
+                .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 void recoverUserLimit(Long id,Integer mode,Integer 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) {
+            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);
+//    }
+
     @Override
-    public MidjourneyUserConversation submitAction(MidjourneyUser user, Long taskId, String customId) throws Exception {
+    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("关联任务不存在或已失效");
@@ -150,63 +215,129 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         if (!user.getMode().equals(conversation.getMode())) {
             throw BusinessRuntimeException.getInstance("当前出图模式与关联任务出图模式不符");
         }
-        AtomicBoolean flag = new AtomicBoolean(false);
+        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 (button.getLabel().contains("Vary") || button.getCustomId().contains("::pan_")
-                            || button.getEmoji().equals("🔄") || button.getCustomId().contains("PromptAnalyzer:")
-                            || button.getCustomId().contains("PicReader::") || button.getCustomId().contains("::variation::")
-                            || button.getCustomId().contains("::CustomZoom::")) {
-                        flag.set(true);
+                    if (!"Vary (Region)".equals(button.getLabel()) && !"Custom Zoom".equals(button.getLabel())) {
+                        modalFlag.set(true);
                     }
                 }
             });
             conversation.setButtons(Jsons.toJson(messageButtons));
         }
-        conversation.setBookmark(customId.contains("BOOKMARK"));
-        conversationMapper.updateById(conversation);
-        if (conversation.getBookmark()) {
-            return conversation;
+        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", param);
-        if (flag.get()) {
-            // 以上操作有弹窗确认,恢复次数
-            recoverUserLimit(user.getId(), user.getMode(),user.getMjRelaxNum());
+                .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);
+            }
         }
-        return saveConversation(user.getId(), user.getMode(), Long.parseLong(result.getResult()),result.getProperties(),"ACTION", StringUtils.EMPTY);
+        saveConversation(user.getId(), user.getMode(), result,"ACTION", StringUtils.EMPTY, botType);
+        return result;
     }
 
 
-    public SubmitResult submit(Integer mode,String action, Map<String, Object> param) throws Exception {
+    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());
         }
-        String url = (mode == 1 ? FAST_HOST : RELAX_HOST) + getActionUrl(action);
+        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("图片重复");
+                throw BusinessRuntimeException.getInstance(submitResult.getDescription());
             }
             if (code == 24) {
-                throw BusinessRuntimeException.getInstance("prompt包含敏感词");
+                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();
+                    }
+                }
+            }
+            return minAccountId;
+        } catch (Exception e) {
+            throw BusinessRuntimeException.getInstance("获取账号失败");
+        }
+    }
     private String getActionUrl(String action) {
          switch (action) {
             case "imagine":
@@ -225,21 +356,36 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         }
     }
     @Override
-    public List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) throws Exception {
+    public List<MidjourneyUserConversation> listConversationByIds(Integer mode, List<Long> ids) {
         List<MidjourneyUserConversation> list = new ArrayList<>();
-        listByIds(mode,ids).forEach(json -> {
-            JSONObject jsons = JSONUtil.parseObj(json);
-            MidjourneyUserConversation conversation = JSONUtil.toBean(jsons, MidjourneyUserConversation.class);
-            conversation.setUserId(jsons.getLong("state"));
-            conversation.setTaskId(jsons.getLong("id"));
-            list.add(conversation);
-            TASK_EXECUTOR.execute(() -> {
+        ids.forEach(id ->{
+            String queryKey = RedisService.key.MIDJOURNEY_QUERY.getName();
+            Long count = redisService.incr(queryKey + id, 1L);
+            if (count%5 == 0) {
                 try {
-                    sync(conversation);
-                } catch (IOException e) {
+                    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;
     }
@@ -248,34 +394,61 @@ public class MidjourneyServiceImpl implements MidjourneyService {
     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, conversation.getUserId()).last("limit 1"));
+                    .eq(MidjourneyUserConversation::getUserId, userId).orderByDesc(MidjourneyUserConversation::getId).last("limit 1"));
             if (dbConversation != null) {
-                try {
-                    if (StringUtils.isNotBlank(conversation.getImageUrl())) {
-                        conversation.setImageUrl(uploadPic(conversation.getImageUrl(), "conversation"+dbConversation.getId()));
+                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);
+                        }
                     }
-                } catch (IOException e) {
-                    log.error("上传图片失败",e);
-                }finally {
-                    conversation.setId(dbConversation.getId());
-                    conversationMapper.updateById(conversation);
+                    midjourneyUserMapper.update(null, wrapper);
                 }
             }
         }
     }
 
-
     private static String uploadPic(String url, String prefix) throws IOException {
         byte[] body = HttpUtil.downloadBytes(url);
         Path tempFile = Files.createTempFile(prefix, ".png");
-        try (FileImageOutputStream imageOutput = new FileImageOutputStream(tempFile.toFile())) {
+        File file = tempFile.toFile();
+        try (FileImageOutputStream imageOutput = new FileImageOutputStream(file)) {
             imageOutput.write(body, 0, body.length);
         }
         Map<String, Object> paramMap = new HashMap<>();
-        paramMap.put("file", tempFile.toFile());
-        JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
-        return result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
+        paramMap.put("file", file);
+        String json = HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap);
+        log.info("上传图片结果:url:{},json:{}",url, json);
+        FileUtil.del(file);
+        return new JSONObject(json).getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl");
     }
 
     private static List<String> uploadBase64Pic(List<String> base64Array) throws IOException {
@@ -293,8 +466,8 @@ public class MidjourneyServiceImpl implements MidjourneyService {
             }
             Map<String, Object> paramMap = new HashMap<>();
             paramMap.put("file", tempFile.toFile());
-            JSONObject result = JSONUtil.parseObj(HttpUtil.post("https://files.liuliangbang.vip/pic/ups", paramMap));
-            list.add(result.getJSONObject("value").getJSONArray("saved").getJSONObject(0).getJSONObject("info").getStr("cdnUrl"));
+            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"));
         }
         return list;
     }
@@ -331,4 +504,23 @@ public class MidjourneyServiceImpl implements MidjourneyService {
         }
     }
 
+    @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);
 }

+ 152 - 32
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)
@@ -451,6 +456,25 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (sku != null && payRequest.getDonMoney().compareTo(sku.getPrice()) < 0 && !isSpecificPrice) {
 			log.info("规格:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", sku.getSpecVal(), payRequest.getDonMoney(), user.getId(), sku.getPrice());
 			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);
+						Long sharedId = distributeShared.getSharedId();
+						List<Long> sharedIdList = goodsDonPriceDto.getSharedId();
+						if (CollUtil.isNotEmpty(sharedIdList) && sharedIdList.contains(sharedId)) {
+							payRequest.setDonMoney(goodsDonPriceDto.getPrice());
+						}
+					}
+				}
+			}
 		}
 
 		//如 mj标准6人月付 价格特殊处理
@@ -1460,6 +1484,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 					}
 					relation.setExpiryTime(newDate);
 					relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
+
+					//镜像续费升级
+					handleMirrorRenew(sku, order, groupsTrips, relation.getId(), newDate);
 				} else if (GroupsTrips.Status.waiting.equals(groupsTrips.getStatus())) {
 					log.info("车位groupsId:{}未发车,修改订单号orderNo:{}订单为已付款状态:{}", groupsTrips.getId(), order.getOrderNo());
 					order.setStatus(OrderDon.Status.hasPayment);
@@ -1502,31 +1529,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);
-//			}
-//		});
 	}
 
 	/**
@@ -3692,13 +3694,90 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	@Override
 	public UpgradeOrderDetailView getUpgradeOrderDetail(Long orderId, Long userId) {
-			MapBuilder builder = MapUtils.builder()
-					.field(OrderDonView::getId, orderId)
-					.orderBy(OrderDonView::getId).desc();
-			if (userId != null) {
-				builder.field(UpgradeOrderDetailView::getUserId, userId);
-			}
-        return beanSearcher.searchFirst(UpgradeOrderDetailView.class, builder.build());
+		MapBuilder builder = MapUtils.builder()
+				.field(OrderDonView::getId, orderId)
+				.orderBy(OrderDonView::getId).desc();
+		if (userId != null) {
+			builder.field(UpgradeOrderDetailView::getUserId, userId);
+		}
+		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;
 	}
 
 	/**
@@ -3711,4 +3790,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) {
+				orderDonRenewRecordMapper.updateById(orderDonRenewRecord);
+				//同规格续费无需更新
+				if (!ObjectUtil.equal(groupsTrips.getSkuId(), order.getSkuId())) {
+					//升级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);
+					}
+				}
+			}
+		}
+	}
 }

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

@@ -138,9 +138,9 @@ public class TransferFuncServiceImpl implements TransferFuncService {
 		if (StrUtil.isEmpty(type)) {
 			type = TransferConstant.ALIPAY;
 		}
-		if (!envCommonService.isPrdEnv()) {
-			name += "xx";
-		}
+//		if (!envCommonService.isPrdEnv()) {
+//			name += "xx";
+//		}
 		Integer scope = transferAccountsReq.getScope();
 		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(sysConfigService.getDefaultShopConfigByType("zfb"));
 

+ 27 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -25,6 +25,7 @@ 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;
@@ -139,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);
@@ -294,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);
@@ -310,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;
@@ -595,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) {
@@ -850,6 +860,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 						.set(GroupsRelation::getStartTime, startTime)
 						.set(GroupsRelation::getExpiryTime, expiryTime)
 						.set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
+						//车票获取类型
 						.set(GroupsRelation::getAqType, 2)
 						.eq(GroupsRelation::getId, relation.getId())
 						.eq(GroupsRelation::getUserId, 0));
@@ -975,4 +986,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());
+			}
+		}
+	}
+
 }

+ 13 - 13
netflix-service/src/main/java/com/cyksj/service/scheduler/SchedulerService.java

@@ -1,13 +1,13 @@
-package com.cyksj.service.scheduler;
-
-/*
- *项目名: netflix
- *文件名: SchedulerService
- *创建者: JavaZou
- *创建时间:2023/6/8 16:47
- */
-public interface SchedulerService {
-	void transExpiryAccountValidRelation();
-
-	void assignUserGroupsRelation(Long groupsId);
-}
+//package com.cyksj.service.scheduler;
+//
+///*
+// *项目名: netflix
+// *文件名: SchedulerService
+// *创建者: JavaZou
+// *创建时间:2023/6/8 16:47
+// */
+//public interface SchedulerService {
+//	void transExpiryAccountValidRelation();
+//
+//	void assignUserGroupsRelation(Long groupsId);
+//}

+ 272 - 272
netflix-service/src/main/java/com/cyksj/service/scheduler/impl/SchedulerServiceImpl.java

@@ -1,272 +1,272 @@
-package com.cyksj.service.scheduler.impl;
-
-import cn.hutool.core.date.DateTime;
-import cn.hutool.core.date.DateUnit;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.constant.Constant;
-import com.cyksj.common.util.StringUtil;
-import com.cyksj.dto.RedisKey;
-import com.cyksj.mapper.*;
-import com.cyksj.model.entity.*;
-import com.cyksj.model.manage.views.GroupsRelationView;
-import com.cyksj.model.request.ChangeRelationReq;
-import com.cyksj.redis.RedisService;
-import com.cyksj.service.error.UserRelationChangeErrorRecordService;
-import com.cyksj.service.groups.GroupsFuncService;
-import com.cyksj.service.mange.CmsOrderDonService;
-import com.cyksj.service.order.OrderRefundService;
-import com.cyksj.service.relation.GroupRelationClearService;
-import com.cyksj.service.scheduler.SchedulerService;
-import com.cyksj.service.user.UserBenefitsService;
-import com.ejlchina.searcher.BeanSearcher;
-import com.ejlchina.searcher.param.Operator;
-import com.ejlchina.searcher.util.MapUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/*
- *项目名: netflix
- *文件名: SchedulerServiceImpl
- *创建者: JavaZou
- *创建时间:2023/6/8 16:48
- */
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class SchedulerServiceImpl implements SchedulerService {
-
-	private final GoodsDonSkuMapper skuMapper;
-
-	private final GroupsMapper groupsMapper;
-
-	private final BeanSearcher beanSearcher;
-
-	private final OrderDonMapper orderDonMapper;
-
-	private final GroupsRelationMapper groupsRelationMapper;
-
-	private final GroupRelationClearService groupRelationClearService;
-
-	private final UserBenefitsService userBenefitsService;
-
-	private final GroupsFuncService groupsFuncService;
-
-	private final OrderRefundService orderRefundService;
-
-	private final CmsOrderDonService cmsOrderDonService;
-
-	private final UserRelationChangeErrorRecordService changeErrorRecordService;
-
-	private final UserRelationChangeErrorRecordMapper userRelationChangeErrorRecordMapper;
-
-	private final GoodsDonMapper goodsDonMapper;
-
-	private final RedisService redisService;
-
-	@Override
-	public void transExpiryAccountValidRelation() {
-		DateTime now = new DateTime();
-		DateTime nextBeginDay = DateUtil.offsetDay(DateUtil.beginOfDay(now), 1);
-		//针对AI类 CHAT PLUS、MidJourney 月付
-		List<Long> aiSkuIds = skuMapper.selectAIMonthSkuIds(Constant.AI_goodsIds);
-		List<GroupsTrips> expiryAccountGroups = groupsMapper.getExpiryAccountGroups(nextBeginDay, aiSkuIds);
-		expiryAccountGroups.forEach(expiry_groups -> {
-			if (expiry_groups.getStatus() != GroupsTrips.Status.down) {
-				expiry_groups.setStatus(GroupsTrips.Status.down);
-				groupsMapper.updateById(expiry_groups);
-			}
-			Long g_groupsId = expiry_groups.getId();
-			Date a_expiryTime = expiry_groups.getExpiryTime();
-			//未过期用户 只分配有效的用户车票 outside状态过滤
-			List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
-					.field(GroupsRelationView::getGroupsId, g_groupsId)
-					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
-					.field(GroupsRelationView::getExpiryTime, nextBeginDay).op(Operator.GreaterEqual)
-					.build());
-			reAssign(g_groupsId, now, groupsRelations, UserTicketClearedRecord.Source.timing_change_ticket);
-		});
-	}
-
-	@Override
-	public void assignUserGroupsRelation(Long groupsId) {
-		GroupsTrips groupsTrips = groupsMapper.selectById(groupsId);
-		if (groupsTrips == null || groupsTrips.getAccountId() == null) return;
-		String key = RedisKey.DISABLE_ACCOUNT_ASSIGN + groupsId;
-		if (!redisService.setNx(key, groupsId, 60 * 3l)) {
-			return;
-		}
-		if (groupsTrips.getStatus() != GroupsTrips.Status.down) {
-			groupsTrips.setStatus(GroupsTrips.Status.down);
-			groupsMapper.updateById(groupsTrips);
-		}
-		DateTime now = DateTime.now();
-		//迁移用户
-		List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
-				.field(GroupsRelationView::getGroupsId, groupsId)
-				.field(GroupsRelationView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
-				.field(GroupsRelationView::getExpiryTime, now).op(Operator.GreaterEqual)
-				.build());
-		reAssign(groupsId, now, groupsRelations, UserTicketClearedRecord.Source.disable);
-		redisService.del(key);
-	}
-
-	/**
-	 * 重新分配车位
-	 */
-	public void reAssign(Long g_groupsId, DateTime now, List<GroupsRelationView> groupsRelations, UserTicketClearedRecord.Source source) {
-		log.info("迁移groupsId:{}未过期用户数量:{}", g_groupsId, groupsRelations.size());
-		Map<Long, GoodsDon> goodsMap = new ConcurrentHashMap<>();
-		Map<Long, GoodsDonSku> skuMap = new ConcurrentHashMap<>();
-		groupsRelations.forEach(relationView -> {
-			Long change_relationId = relationView.getId();
-			Long userId = relationView.getUserId();
-			UserRelationChangeErrorRecord exists = userRelationChangeErrorRecordMapper.selectOne(Wrappers.lambdaQuery(UserRelationChangeErrorRecord.class)
-					.eq(UserRelationChangeErrorRecord::getRelationId, change_relationId)
-					.eq(UserRelationChangeErrorRecord::getUserId, userId)
-					.eq(UserRelationChangeErrorRecord::getDeleted, true)
-					.last("limit 1"));
-			if (exists != null) {
-				log.info("存在userId:{}无法转移的车票relationId:{}", userId, change_relationId);
-				return;
-			}
-			Date expiryTime = DateUtil.beginOfDay(relationView.getExpiryTime());
-			Long skuId = relationView.getSkuId();
-			//仅针对chatGPT
-			if (Constant.AI_goodsIds.contains(relationView.getGoodsId())) {
-				Long bet_day = DateUtil.between(now, expiryTime, DateUnit.DAY);
-				//10人月付 10天内硬塞20个 10天外硬塞10个
-				//4人月付 硬塞5个
-				Integer extra_num = 5;
-				//10天以内
-				if (bet_day <= 10) {
-					if (skuId.equals(161l)) {
-						extra_num = 20;
-					}
-					//分配到过期账号5天内误差的相同规格车队里
-					DateTime five_day = DateUtil.offsetDay(expiryTime, 5);
-					Long item_groupsId = groupsMapper.selectSameSpecItemGroupsByTime(g_groupsId, skuId, expiryTime, five_day, extra_num);
-					if (item_groupsId == null) {
-						//无对应车队 退款
-						//退款至余额
-						OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
-								.eq(OrderDon::getRelationId, change_relationId)
-								.eq(OrderDon::getUserId, userId)
-								.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
-								.orderByDesc(OrderDon::getId)
-								.last("limit 1"));
-						if (orderDon == null) {
-							//更换过车票
-							orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
-									.eq(OrderDon::getSkuId, skuId)
-									.eq(OrderDon::getUserId, userId)
-									.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
-									.orderByDesc(OrderDon::getId)
-									.last("limit 1"));
-						}
-						if (orderDon == null) {
-							log.error("用户userId:{}的车票relationId:{}账号过期后转移错误", userId, change_relationId);
-							changeErrorRecordService.changeTicketErrorRecord(relationView, UserRelationChangeErrorRecord.Source.change);
-							return;
-						}
-						//清除车票
-						GroupsRelation relation = groupsRelationMapper.selectById(change_relationId);
-						groupRelationClearService.clearTicket(relation, UserTicketClearedRecord.Source.refund_balance);
-						//退款至余额
-						//实付金额 + 余额
-						BigDecimal money = orderDon.getMoney().add(orderDon.getBalance());
-						//当月天数
-						Date payTime = orderDon.getPayTime();
-						if (payTime == null) {
-							payTime = orderDon.getCreatedTime();
-						}
-						if (money.compareTo(BigDecimal.ZERO) == 0) {
-							GoodsDonSku sku = skuMapper.selectById(skuId);
-							if (sku != null) {
-								money = sku.getPrice();
-							}
-						}
-						int dayNum = DateUtil.dayOfMonth(DateUtil.endOfMonth(payTime));
-						BigDecimal re_balance = money.divide(BigDecimal.valueOf(dayNum), 0, RoundingMode.DOWN).multiply(BigDecimal.valueOf(bet_day));
-						if (re_balance.compareTo(BigDecimal.ZERO) <= 0) {
-							log.info("user_id:{},relationId:{}返回余额为0", userId, change_relationId);
-							return;
-						}
-						GoodsDon goodsDon = goodsMap.get(relationView.getGoodsId());
-						if (goodsDon == null) {
-							goodsDon = goodsDonMapper.selectById(relationView.getGoodsId());
-							if (goodsDon == null) return;
-							goodsMap.putIfAbsent(relationView.getGoodsId(), goodsDon);
-						}
-						userBenefitsService.addUserBalance(userId, re_balance, UserBalanceSourceRecord.Source.clear_valid, relationView.getYhsId(), orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.clear_valid.getDesc(), true);
-						log.info("车票未到期清除,退款至用户user_id:{}余额:{}成功", userId, re_balance);
-						//修改订单状态 为退款
-						orderDon.setStatus(OrderDon.Status.refund);
-						orderDon.setRefundBalance(re_balance);
-						orderDon.setRefundMoney(BigDecimal.ZERO);
-						orderDonMapper.updateById(orderDon);
-						GoodsDonSku sku = skuMap.get(orderDon.getSkuId());
-						if (sku == null) {
-							sku = skuMapper.selectById(orderDon.getSkuId());
-							if (sku == null) return;
-							skuMap.putIfAbsent(orderDon.getSkuId(), sku);
-						}
-						orderRefundService.refundRecord(orderDon, orderDon.getRefundMoney(), null, goodsDon, sku, StrUtil.EMPTY, "balance", null);
-						return;
-					}
-					changeTickerRelation(item_groupsId, relationView, source, relationView.getYhsId());
-					return;
-				}
-				//大于10天
-				//分配到过期账号10天内误差的相同规格车队里
-				if (skuId.equals(161l)) {
-					extra_num = 10;
-				}
-				DateTime ten_day = DateUtil.offsetDay(expiryTime, 10);
-				Long item_groupsId = groupsMapper.selectSameSpecItemGroupsByTime(g_groupsId, skuId, expiryTime, ten_day, extra_num);
-				if (item_groupsId == null) {
-					//无对应车队 生成空车队
-					//寻找空车队
-					item_groupsId = groupsMapper.selectSameSpecEmptyGroups(skuId);
-					if (item_groupsId == null) {
-						//新增空车队
-						GoodsDonSku sku = skuMapper.selectById(skuId);
-						GroupsRelation new_relation = groupsFuncService.createNewGroupsTrips(sku);
-						item_groupsId = new_relation.getGroupsId();
-					}
-					//新车队
-					changeTickerRelation(item_groupsId, relationView, UserTicketClearedRecord.Source.new_groups_ticket, relationView.getYhsId());
-					return;
-				}
-				changeTickerRelation(item_groupsId, relationView, source, relationView.getYhsId());
-				return;
-			}
-		});
-	}
-
-	public void changeTickerRelation(Long item_groupsId, GroupsRelationView relationView, UserTicketClearedRecord.Source source, Long yhsId) {
-		Long change_relationId = relationView.getId();
-		try {
-			ChangeRelationReq req = new ChangeRelationReq();
-			req.setGroupsId(item_groupsId);
-			req.setRelationId(change_relationId);
-			req.setSource(source);
-			req.setIsOutside(true);
-			req.setYhsId(yhsId);
-			cmsOrderDonService.changeRelation(req);
-		} catch (Exception e) {
-			log.error("更换用户relationId:{}错误:{}", change_relationId, StringUtil.getErrorText(e));
-			relationView.setErrorMsg(StringUtil.getErrorMsg(e));
-			changeErrorRecordService.changeTicketErrorRecord(relationView, UserRelationChangeErrorRecord.Source.change);
-		}
-	}
-}
+//package com.cyksj.service.scheduler.impl;
+//
+//import cn.hutool.core.date.DateTime;
+//import cn.hutool.core.date.DateUnit;
+//import cn.hutool.core.date.DateUtil;
+//import cn.hutool.core.util.StrUtil;
+//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+//import com.cyksj.common.constant.Constant;
+//import com.cyksj.common.util.StringUtil;
+//import com.cyksj.dto.RedisKey;
+//import com.cyksj.mapper.*;
+//import com.cyksj.model.entity.*;
+//import com.cyksj.model.manage.views.GroupsRelationView;
+//import com.cyksj.model.request.ChangeRelationReq;
+//import com.cyksj.redis.RedisService;
+//import com.cyksj.service.error.UserRelationChangeErrorRecordService;
+//import com.cyksj.service.groups.GroupsFuncService;
+//import com.cyksj.service.mange.CmsOrderDonService;
+//import com.cyksj.service.order.OrderRefundService;
+//import com.cyksj.service.relation.GroupRelationClearService;
+//import com.cyksj.service.scheduler.SchedulerService;
+//import com.cyksj.service.user.UserBenefitsService;
+//import com.ejlchina.searcher.BeanSearcher;
+//import com.ejlchina.searcher.param.Operator;
+//import com.ejlchina.searcher.util.MapUtils;
+//import lombok.RequiredArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Service;
+//
+//import java.math.BigDecimal;
+//import java.math.RoundingMode;
+//import java.util.Date;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+///*
+// *项目名: netflix
+// *文件名: SchedulerServiceImpl
+// *创建者: JavaZou
+// *创建时间:2023/6/8 16:48
+// */
+//@Service
+//@RequiredArgsConstructor
+//@Slf4j
+//public class SchedulerServiceImpl implements SchedulerService {
+//
+//	private final GoodsDonSkuMapper skuMapper;
+//
+//	private final GroupsMapper groupsMapper;
+//
+//	private final BeanSearcher beanSearcher;
+//
+//	private final OrderDonMapper orderDonMapper;
+//
+//	private final GroupsRelationMapper groupsRelationMapper;
+//
+//	private final GroupRelationClearService groupRelationClearService;
+//
+//	private final UserBenefitsService userBenefitsService;
+//
+//	private final GroupsFuncService groupsFuncService;
+//
+//	private final OrderRefundService orderRefundService;
+//
+//	private final CmsOrderDonService cmsOrderDonService;
+//
+//	private final UserRelationChangeErrorRecordService changeErrorRecordService;
+//
+//	private final UserRelationChangeErrorRecordMapper userRelationChangeErrorRecordMapper;
+//
+//	private final GoodsDonMapper goodsDonMapper;
+//
+//	private final RedisService redisService;
+//
+//	@Override
+//	public void transExpiryAccountValidRelation() {
+//		DateTime now = new DateTime();
+//		DateTime nextBeginDay = DateUtil.offsetDay(DateUtil.beginOfDay(now), 1);
+//		//针对AI类 CHAT PLUS、MidJourney 月付
+//		List<Long> aiSkuIds = skuMapper.selectAIMonthSkuIds(Constant.AI_goodsIds);
+//		List<GroupsTrips> expiryAccountGroups = groupsMapper.getExpiryAccountGroups(nextBeginDay, aiSkuIds);
+//		expiryAccountGroups.forEach(expiry_groups -> {
+//			if (expiry_groups.getStatus() != GroupsTrips.Status.down) {
+//				expiry_groups.setStatus(GroupsTrips.Status.down);
+//				groupsMapper.updateById(expiry_groups);
+//			}
+//			Long g_groupsId = expiry_groups.getId();
+//			Date a_expiryTime = expiry_groups.getExpiryTime();
+//			//未过期用户 只分配有效的用户车票 outside状态过滤
+//			List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+//					.field(GroupsRelationView::getGroupsId, g_groupsId)
+//					.field(GroupsRelationView::getStatus, GroupsRelation.Status.validity.name())
+//					.field(GroupsRelationView::getExpiryTime, nextBeginDay).op(Operator.GreaterEqual)
+//					.build());
+//			reAssign(g_groupsId, now, groupsRelations, UserTicketClearedRecord.Source.timing_change_ticket);
+//		});
+//	}
+//
+//	@Override
+//	public void assignUserGroupsRelation(Long groupsId) {
+//		GroupsTrips groupsTrips = groupsMapper.selectById(groupsId);
+//		if (groupsTrips == null || groupsTrips.getAccountId() == null) return;
+//		String key = RedisKey.DISABLE_ACCOUNT_ASSIGN + groupsId;
+//		if (!redisService.setNx(key, groupsId, 60 * 3l)) {
+//			return;
+//		}
+//		if (groupsTrips.getStatus() != GroupsTrips.Status.down) {
+//			groupsTrips.setStatus(GroupsTrips.Status.down);
+//			groupsMapper.updateById(groupsTrips);
+//		}
+//		DateTime now = DateTime.now();
+//		//迁移用户
+//		List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+//				.field(GroupsRelationView::getGroupsId, groupsId)
+//				.field(GroupsRelationView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
+//				.field(GroupsRelationView::getExpiryTime, now).op(Operator.GreaterEqual)
+//				.build());
+//		reAssign(groupsId, now, groupsRelations, UserTicketClearedRecord.Source.disable);
+//		redisService.del(key);
+//	}
+//
+//	/**
+//	 * 重新分配车位
+//	 */
+//	public void reAssign(Long g_groupsId, DateTime now, List<GroupsRelationView> groupsRelations, UserTicketClearedRecord.Source source) {
+//		log.info("迁移groupsId:{}未过期用户数量:{}", g_groupsId, groupsRelations.size());
+//		Map<Long, GoodsDon> goodsMap = new ConcurrentHashMap<>();
+//		Map<Long, GoodsDonSku> skuMap = new ConcurrentHashMap<>();
+//		groupsRelations.forEach(relationView -> {
+//			Long change_relationId = relationView.getId();
+//			Long userId = relationView.getUserId();
+//			UserRelationChangeErrorRecord exists = userRelationChangeErrorRecordMapper.selectOne(Wrappers.lambdaQuery(UserRelationChangeErrorRecord.class)
+//					.eq(UserRelationChangeErrorRecord::getRelationId, change_relationId)
+//					.eq(UserRelationChangeErrorRecord::getUserId, userId)
+//					.eq(UserRelationChangeErrorRecord::getDeleted, true)
+//					.last("limit 1"));
+//			if (exists != null) {
+//				log.info("存在userId:{}无法转移的车票relationId:{}", userId, change_relationId);
+//				return;
+//			}
+//			Date expiryTime = DateUtil.beginOfDay(relationView.getExpiryTime());
+//			Long skuId = relationView.getSkuId();
+//			//仅针对chatGPT
+//			if (Constant.AI_goodsIds.contains(relationView.getGoodsId())) {
+//				Long bet_day = DateUtil.between(now, expiryTime, DateUnit.DAY);
+//				//10人月付 10天内硬塞20个 10天外硬塞10个
+//				//4人月付 硬塞5个
+//				Integer extra_num = 5;
+//				//10天以内
+//				if (bet_day <= 10) {
+//					if (skuId.equals(161l)) {
+//						extra_num = 20;
+//					}
+//					//分配到过期账号5天内误差的相同规格车队里
+//					DateTime five_day = DateUtil.offsetDay(expiryTime, 5);
+//					Long item_groupsId = groupsMapper.selectSameSpecItemGroupsByTime(g_groupsId, skuId, expiryTime, five_day, extra_num);
+//					if (item_groupsId == null) {
+//						//无对应车队 退款
+//						//退款至余额
+//						OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
+//								.eq(OrderDon::getRelationId, change_relationId)
+//								.eq(OrderDon::getUserId, userId)
+//								.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
+//								.orderByDesc(OrderDon::getId)
+//								.last("limit 1"));
+//						if (orderDon == null) {
+//							//更换过车票
+//							orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
+//									.eq(OrderDon::getSkuId, skuId)
+//									.eq(OrderDon::getUserId, userId)
+//									.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
+//									.orderByDesc(OrderDon::getId)
+//									.last("limit 1"));
+//						}
+//						if (orderDon == null) {
+//							log.error("用户userId:{}的车票relationId:{}账号过期后转移错误", userId, change_relationId);
+//							changeErrorRecordService.changeTicketErrorRecord(relationView, UserRelationChangeErrorRecord.Source.change);
+//							return;
+//						}
+//						//清除车票
+//						GroupsRelation relation = groupsRelationMapper.selectById(change_relationId);
+//						groupRelationClearService.clearTicket(relation, UserTicketClearedRecord.Source.refund_balance);
+//						//退款至余额
+//						//实付金额 + 余额
+//						BigDecimal money = orderDon.getMoney().add(orderDon.getBalance());
+//						//当月天数
+//						Date payTime = orderDon.getPayTime();
+//						if (payTime == null) {
+//							payTime = orderDon.getCreatedTime();
+//						}
+//						if (money.compareTo(BigDecimal.ZERO) == 0) {
+//							GoodsDonSku sku = skuMapper.selectById(skuId);
+//							if (sku != null) {
+//								money = sku.getPrice();
+//							}
+//						}
+//						int dayNum = DateUtil.dayOfMonth(DateUtil.endOfMonth(payTime));
+//						BigDecimal re_balance = money.divide(BigDecimal.valueOf(dayNum), 0, RoundingMode.DOWN).multiply(BigDecimal.valueOf(bet_day));
+//						if (re_balance.compareTo(BigDecimal.ZERO) <= 0) {
+//							log.info("user_id:{},relationId:{}返回余额为0", userId, change_relationId);
+//							return;
+//						}
+//						GoodsDon goodsDon = goodsMap.get(relationView.getGoodsId());
+//						if (goodsDon == null) {
+//							goodsDon = goodsDonMapper.selectById(relationView.getGoodsId());
+//							if (goodsDon == null) return;
+//							goodsMap.putIfAbsent(relationView.getGoodsId(), goodsDon);
+//						}
+//						userBenefitsService.addUserBalance(userId, re_balance, UserBalanceSourceRecord.Source.clear_valid, relationView.getYhsId(), orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.clear_valid.getDesc(), true);
+//						log.info("车票未到期清除,退款至用户user_id:{}余额:{}成功", userId, re_balance);
+//						//修改订单状态 为退款
+//						orderDon.setStatus(OrderDon.Status.refund);
+//						orderDon.setRefundBalance(re_balance);
+//						orderDon.setRefundMoney(BigDecimal.ZERO);
+//						orderDonMapper.updateById(orderDon);
+//						GoodsDonSku sku = skuMap.get(orderDon.getSkuId());
+//						if (sku == null) {
+//							sku = skuMapper.selectById(orderDon.getSkuId());
+//							if (sku == null) return;
+//							skuMap.putIfAbsent(orderDon.getSkuId(), sku);
+//						}
+//						orderRefundService.refundRecord(orderDon, orderDon.getRefundMoney(), null, goodsDon, sku, StrUtil.EMPTY, "balance", null);
+//						return;
+//					}
+//					changeTickerRelation(item_groupsId, relationView, source, relationView.getYhsId());
+//					return;
+//				}
+//				//大于10天
+//				//分配到过期账号10天内误差的相同规格车队里
+//				if (skuId.equals(161l)) {
+//					extra_num = 10;
+//				}
+//				DateTime ten_day = DateUtil.offsetDay(expiryTime, 10);
+//				Long item_groupsId = groupsMapper.selectSameSpecItemGroupsByTime(g_groupsId, skuId, expiryTime, ten_day, extra_num);
+//				if (item_groupsId == null) {
+//					//无对应车队 生成空车队
+//					//寻找空车队
+//					item_groupsId = groupsMapper.selectSameSpecEmptyGroups(skuId);
+//					if (item_groupsId == null) {
+//						//新增空车队
+//						GoodsDonSku sku = skuMapper.selectById(skuId);
+//						GroupsRelation new_relation = groupsFuncService.createNewGroupsTrips(sku);
+//						item_groupsId = new_relation.getGroupsId();
+//					}
+//					//新车队
+//					changeTickerRelation(item_groupsId, relationView, UserTicketClearedRecord.Source.new_groups_ticket, relationView.getYhsId());
+//					return;
+//				}
+//				changeTickerRelation(item_groupsId, relationView, source, relationView.getYhsId());
+//				return;
+//			}
+//		});
+//	}
+//
+//	public void changeTickerRelation(Long item_groupsId, GroupsRelationView relationView, UserTicketClearedRecord.Source source, Long yhsId) {
+//		Long change_relationId = relationView.getId();
+//		try {
+//			ChangeRelationReq req = new ChangeRelationReq();
+//			req.setGroupsId(item_groupsId);
+//			req.setRelationId(change_relationId);
+//			req.setSource(source);
+//			req.setIsOutside(true);
+//			req.setYhsId(yhsId);
+//			cmsOrderDonService.changeRelation(req);
+//		} catch (Exception e) {
+//			log.error("更换用户relationId:{}错误:{}", change_relationId, StringUtil.getErrorText(e));
+//			relationView.setErrorMsg(StringUtil.getErrorMsg(e));
+//			changeErrorRecordService.changeTicketErrorRecord(relationView, UserRelationChangeErrorRecord.Source.change);
+//		}
+//	}
+//}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysConfigChangeRecordServiceImpl.java

@@ -134,7 +134,7 @@ public class SysConfigChangeRecordServiceImpl extends ServiceImpl<SysConfigChang
 					DayOfWeek nowDayOfWeek = LocalDateTime.now().getDayOfWeek();
 					if (weekdayMsgNotifySb.length() > 0 && (nowDayOfWeek == DayOfWeek.SATURDAY || nowDayOfWeek == DayOfWeek.SUNDAY) && envCommonService.isPrdEnv()) {
 						//一个小时内 不重复发送
-						if (redisService.setNx(RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getEnvName(), RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getName(), RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getTimeout())) {
+						if (redisService.setNx(RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getName(), RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getName(), RedisService.key.WEEKEND_DUTY_UNDERSTAFFED_NOTIFY.getTimeout())) {
 							SmsUtil.sendLuoKey2Msg(Constant.DUTY_SERVICE_CHANGE_NOTIFY_PHONE, String.format(Constant.DUTY_SERVICE_CHANGE_MSG, weekdayMsgNotifySb));
 						}
 					}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/sys/impl/SysFuncTimingShelfServiceImpl.java

@@ -83,7 +83,7 @@ public class SysFuncTimingShelfServiceImpl extends ServiceImpl<SysFuncTimingShel
 				homeManagementConfigMapper.updateById(homeManagementConfig);
 				log.info("将首页配置:{}的状态置为:{}状态", funcId, timingShelf.getPreStatus());
 
-				Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "*");
+				Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "*");
 				redisService.del(keys.toArray(String[]::new));
 			});
 		});

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

@@ -105,7 +105,7 @@ public class UserIdentCertServiceImpl implements UserIdentCertService {
 			return null;
 		}
 		String state = StringUtil.randomString(6);
-		redisService.set(RedisService.key.WX_INDENT_BIND_KEY.getEnvName() + state, userId, RedisService.key.WX_INDENT_BIND_KEY.getTimeout());
+		redisService.set(RedisService.key.WX_INDENT_BIND_KEY.getName() + state, userId, RedisService.key.WX_INDENT_BIND_KEY.getTimeout());
 		return state;
 	}
 
@@ -118,7 +118,7 @@ public class UserIdentCertServiceImpl implements UserIdentCertService {
 //		if (userIdList.size() == 1 && StrUtil.isNotEmpty(bindState)) {
 //			User user = userMapper.selectById(userId);
 //			if (StrUtil.isEmpty(user.getOpenId())) {
-//				String key = RedisService.key.WX_INDENT_BIND_KEY.getEnvName() + bindState;
+//				String key = RedisService.key.WX_INDENT_BIND_KEY.getName() + bindState;
 //				Object bindInfo = redisService.get(key);
 //				if (bindInfo == null) {
 //					throw BusinessRuntimeException.getInstance("认证信息已失效,请重新操作..");

+ 83 - 83
netflix-service/src/main/java/com/cyksj/task/CorpChatScheduler.java

@@ -1,83 +1,83 @@
-package com.cyksj.task;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.cyksj.common.util.StringUtil;
-import com.cyksj.mapper.corp.CorpUserAuthMapper;
-import com.cyksj.mapper.corp.CorpUserMapper;
-import com.cyksj.model.entity.CorpUser;
-import com.cyksj.model.entity.CorpUserAuth;
-import com.cyksj.model.entity.OrderDonPost;
-import com.cyksj.redis.RedisService;
-import com.cyksj.service.corp.WxCorpOps;
-import com.cyksj.service.corp.msg.CorpEventActionService;
-import com.cyksj.service.order.OrderDonPostService;
-import com.ejlchina.searcher.BeanSearcher;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * @author chan
- * @date 2024-04-29 12:14
- */
-@Component
-@Slf4j
-@RequiredArgsConstructor
-public class CorpChatScheduler {
-
-	private final CorpUserMapper corpUserMapper;
-
-	private final CorpUserAuthMapper corpUserAuthMapper;
-
-	private final RedisService redisService;
-
-	private final OrderDonPostService orderDonPostService;
-
-	/**
-	 * 客服业绩数据统计
-	 */
-    @Scheduled(cron = "5 0/2 * * * ?")
-	public void chatPost() {
-		Set<Object> chatRecord = redisService.sGet(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName());
-		log.info("发起对话回传. size: {}", chatRecord.size());
-		chatRecord.forEach((key) -> {
-			log.info("发起对话回传. key: {}", key);
-			CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class)
-					.eq(CorpUserAuth::getExternalUserid, key).last("limit 1"));
-			String unionId = null;
-			if (corpUserAuth != null) {
-				CorpUser corpUser = corpUserMapper.selectById(corpUserAuth.getCorpUserId());
-				if (corpUser != null) {
-					unionId = corpUser.getUnionid();
-				}
-			}
-			log.info("发起对话回传. unionId: {}", unionId);
-			if (StrUtil.isNotBlank(unionId)) {
-				String json = StringUtil.getString(redisService.hget(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getEnvName(), unionId));
-				if (StringUtil.isNotBlank(json)) {
-					JSONObject jsonObject = JSONUtil.parseObj(json);
-					String callback = jsonObject.getStr("callback");
-					try {
-						orderDonPostService.post(OrderDonPost.Type.OE.getType(), callback, Optional.ofNullable(jsonObject.getStr("event")).orElse("customer_effective"));
-						redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
-						log.info("发起对话回传成功. {}", key);
-					} catch (Exception e) {
-						log.error("发起对话回传失败. {}", e.getMessage());
-					}
-				}
-			}else {
-				Long count = redisService.incr(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_COUNT.getNameFormat(key), 1L);
-				if(count > 3){
-					redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
-				}
-			}
-		});
-	}
-}
+//package com.cyksj.task;
+//
+//import cn.hutool.core.util.StrUtil;
+//import cn.hutool.json.JSONObject;
+//import cn.hutool.json.JSONUtil;
+//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+//import com.cyksj.common.util.StringUtil;
+//import com.cyksj.mapper.corp.CorpUserAuthMapper;
+//import com.cyksj.mapper.corp.CorpUserMapper;
+//import com.cyksj.model.entity.CorpUser;
+//import com.cyksj.model.entity.CorpUserAuth;
+//import com.cyksj.model.entity.OrderDonPost;
+//import com.cyksj.redis.RedisService;
+//import com.cyksj.service.corp.WxCorpOps;
+//import com.cyksj.service.corp.msg.CorpEventActionService;
+//import com.cyksj.service.order.OrderDonPostService;
+//import com.ejlchina.searcher.BeanSearcher;
+//import lombok.RequiredArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.scheduling.annotation.Scheduled;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.Optional;
+//import java.util.Set;
+//
+///**
+// * @author chan
+// * @date 2024-04-29 12:14
+// */
+//@Component
+//@Slf4j
+//@RequiredArgsConstructor
+//public class CorpChatScheduler {
+//
+//	private final CorpUserMapper corpUserMapper;
+//
+//	private final CorpUserAuthMapper corpUserAuthMapper;
+//
+//	private final RedisService redisService;
+//
+//	private final OrderDonPostService orderDonPostService;
+//
+//	/**
+//	 * 客服业绩数据统计
+//	 */
+//    @Scheduled(cron = "5 0/2 * * * ?")
+//	public void chatPost() {
+//		Set<Object> chatRecord = redisService.sGet(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName());
+//		log.info("发起对话回传. size: {}", chatRecord.size());
+//		chatRecord.forEach((key) -> {
+//			log.info("发起对话回传. key: {}", key);
+//			CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class)
+//					.eq(CorpUserAuth::getExternalUserid, key).last("limit 1"));
+//			String unionId = null;
+//			if (corpUserAuth != null) {
+//				CorpUser corpUser = corpUserMapper.selectById(corpUserAuth.getCorpUserId());
+//				if (corpUser != null) {
+//					unionId = corpUser.getUnionid();
+//				}
+//			}
+//			log.info("发起对话回传. unionId: {}", unionId);
+//			if (StrUtil.isNotBlank(unionId)) {
+//				String json = StringUtil.getString(redisService.hget(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getEnvName(), unionId));
+//				if (StringUtil.isNotBlank(json)) {
+//					JSONObject jsonObject = JSONUtil.parseObj(json);
+//					String callback = jsonObject.getStr("callback");
+//					try {
+//						orderDonPostService.post(OrderDonPost.Type.OE.getType(), callback, Optional.ofNullable(jsonObject.getStr("event")).orElse("customer_effective"));
+//						redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
+//						log.info("发起对话回传成功. {}", key);
+//					} catch (Exception e) {
+//						log.error("发起对话回传失败. {}", e.getMessage());
+//					}
+//				}
+//			}else {
+//				Long count = redisService.incr(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_COUNT.getNameFormat(key), 1L);
+//				if(count > 3){
+//					redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
+//				}
+//			}
+//		});
+//	}
+//}

+ 4 - 16
netflix-web/src/main/java/com/cyksj/web/controller/cps/CpsBackLoginController.java

@@ -32,6 +32,7 @@ import com.cyksj.service.cps.CpsManageService;
 import com.cyksj.service.wechat.WeChatService;
 import com.cyksj.web.util.StpCpsManageUser;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -101,15 +102,11 @@ public class CpsBackLoginController {
 	@GetMapping("/wx/authLogin")
 	public Result<CpsAuthDto> wxAuthorize(String redirectUrl) throws Exception {
 		CpsAuthDto cpsAuthDto = new CpsAuthDto();
-		Long mappingId = SEQUENCE.nextId();
-		String authState = mappingId.toString();
-		redisService.set(authState, authState, 60 * 60 * 24L);
-		AuthRedirect redirect = new AuthRedirect().setMappingId(mappingId);
+		AuthRedirect redirect = new AuthRedirect();
 		redirect.setUrl(redirectUrl);
 		String state = Codec.DoBase64.custom().setData(Jsons.toJson(redirect)).encodeAsText();
 		String wxAuthUrl = authorizationService.createWxAuthLoginUrl(state, wxOpenPlatYHLXLoginConfig.getAppId(), wxOpenPlatYHLXLoginConfig.getCpsRedirectUri());
 		cpsAuthDto.setAuthUrl(wxAuthUrl);
-		cpsAuthDto.setAuthState(authState);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(cpsAuthDto);
 	}
 
@@ -137,17 +134,8 @@ public class CpsBackLoginController {
 		if (userDistribute == null) throw BusinessRuntimeException.getInstance("只支持渠道分销用户登录");
 		StpCpsManageUser.login(user.getId());
 		String cpsToken = StpCpsManageUser.getTokenValue();
-		String url = re.getUrl();
-		if (StrUtil.isNotBlank(url)) {
-			response.sendRedirect(url.contains("?") ? url + "&t=" + cpsToken : url + "?t=" + cpsToken);
-			return;
-		}
-		JSONObject res = new JSONObject();
-		res.putOpt("satoken-cpsUser", cpsToken);
-		res.putOpt("img", user.getHeadimgurl());
-		res.putOpt("nickname", user.getNickname());
-		redisService.set(RedisService.key.CPS_AUTH_SUCCESS_KEY.getNameFormat(re.getMappingId()), res.toString(), RedisService.key.CPS_BACK_LOGIN_KEY.getTimeout());
-		response.sendRedirect(wxOpenPlatYHLXLoginConfig.getCpsLoginUrl());
+		String url = Optional.ofNullable(re.getUrl()).orElse(wxOpenPlatYHLXLoginConfig.getLoginUrl());
+		response.sendRedirect(url.contains("?") ? url + "&t=" + cpsToken : url + "?t=" + cpsToken);
 	}
 
 	/**

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

@@ -97,7 +97,7 @@ public class GoodsDonController {
 	    if (StrUtil.isNotBlank(customId)) {
 		    yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
 	    }
-	    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "category";
+	    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category";
 	    if (yhsId != null) {
 		    key += ":yhShop:" + yhsId;
 	    }
@@ -232,7 +232,7 @@ public class GoodsDonController {
 	    }
 	    //List<Long> filter_goodsIds = getFilterGoodsIds();
 	    List<Long> filter_goodsIds = null;
-	    String pcCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "PC";
+	    String pcCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "PC";
 	    if (CollUtil.isNotEmpty(filter_goodsIds)) {
 		    pcCacheKey += ":hz-ip";
 	    }
@@ -275,7 +275,7 @@ public class GoodsDonController {
 	    }
 	    //List<Long> filter_goodsIds = getFilterGoodsIds();
 		List<Long> filter_goodsIds = null;
-	    String h5CacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "H5";
+	    String h5CacheKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "H5";
 	    if (CollUtil.isNotEmpty(filter_goodsIds)) {
 		    h5CacheKey += ":hz-ip";
 	    }
@@ -311,7 +311,7 @@ public class GoodsDonController {
      */
     @GetMapping("/get/register")
     public Result<List<RegisterGoodsDonView>> getRegisterGoodsDon() {
-        String registerCacheKey = RedisService.key.REGISTER_HOME_PAGE_CACHE.getEnvName();
+        String registerCacheKey = RedisService.key.REGISTER_HOME_PAGE_CACHE.getName();
         Object value = redisService.get(registerCacheKey);
         if (value != null) {
             try {
@@ -451,11 +451,11 @@ public class GoodsDonController {
      */
     @GetMapping("/get/recommend/{id}")
     public Result<List<GoodsFrontListView>> getRecommendGoodsByGid(@PathVariable Long id, String customId, String dsCode) throws Exception {
-	    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "recommend:" + id;
+	    String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "recommend:" + id;
 	    Long yhsId = null;
 	    if (StrUtil.isNotBlank(customId)) {
 		    yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
-		    key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhsId + ":recommend:" + id;
+		    key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":recommend:" + id;
 	    }
 	    Object o = redisService.get(key);
 	    Long fUid = StpUserUtil.getUserIdAfterLogin();
@@ -555,11 +555,11 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/homeManage")
 	public Result<Map<String, List<HomeManagementFrontView>>> getHomeManagementFrontPage(String customId, String dsCode) {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "homeManage";
+		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "homeManage";
 		Long yhsId = null;
 		if (StrUtil.isNotBlank(customId)) {
 			yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
-			key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhsId + ":homeManage";
+			key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":homeManage";
 		}
 //		List<Long> filter_goodsIds = getFilterGoodsIds();
 		List<Long> filter_goodsIds = null;
@@ -734,7 +734,7 @@ public class GoodsDonController {
 	    if (fUid != null) {
 		    if (data.getIsSp()) {
 			    //查找所有特定规格最小价格 满足条件
-			    String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "specific:" + data.getId();
+			    String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "specific:" + data.getId();
 			    Object speciObj = redisService.get(specificGoodsKey);
 			    List<GoodsDonSku> specificSkus = null;
 			    if (speciObj != null) {
@@ -786,7 +786,7 @@ public class GoodsDonController {
 		if (fUid != null) {
 			if (data.getIsSp()) {
 				//查找所有特定规格最小价格 满足条件
-				String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "specific:" + data.getId();
+				String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "specific:" + data.getId();
 				Object speciObj = redisService.get(specificGoodsKey);
 				List<GoodsDonSku> specificSkus = null;
 				if (speciObj != null) {
@@ -836,7 +836,7 @@ public class GoodsDonController {
 	 */
 	public List<GoodsDonSku> getSpecificSku(Long goodsId) {
 		//查找所有特定规格最小价格 满足条件
-		String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "specific:" + goodsId;
+		String specificGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "specific:" + goodsId;
 		Object speciObj = redisService.get(specificGoodsKey);
 		List<GoodsDonSku> specificSkus = null;
 		if (speciObj != null) {
@@ -918,7 +918,7 @@ public class GoodsDonController {
      */
     @GetMapping("/get/shop/goods/{yhsId}")
     public Result<List<YhShopGoodsFrontView>> getShopGoods(@PathVariable Long yhsId) {
-        String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhsId;
+        String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId;
         Object value = redisService.get(yhShopCacheKey);
         List<YhShopGoodsFrontView> list = null;
         if (value != null) {
@@ -974,7 +974,7 @@ public class GoodsDonController {
 			return shopGoods;
 		}
 		Long fUid = StpUserUtil.getUserIdAfterLogin();
-		String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "category:goods";
+		String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "category:goods";
 		if (cgy != null) {
 			categoryGoodsKey += ":" + cgy;
 		}
@@ -1052,7 +1052,7 @@ public class GoodsDonController {
 
 	@GetMapping("/get/shop/categoryGoods/{yhsId}")
 	public Result<List<YhShopGoodsFrontCategoryView>> getShopCategoryGoods(@PathVariable Long yhsId, Long category) {
-		String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhsId + ":category";
+		String categoryGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getName() + yhsId + ":category";
 		if (category != null) {
 			categoryGoodsKey += ":" + category;
 		}
@@ -1102,7 +1102,7 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/deposit")
 	public Result<? extends Object> getDepositGoods() {
-		String depositGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "deposit";
+		String depositGoodsKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "deposit";
 		Object o = redisService.get(depositGoodsKey);
 		if (o == null) {
 			List<GoodsDon> depositList = beanSearcher.searchAll(GoodsDon.class, MapUtils.builder()
@@ -1126,7 +1126,7 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/pc/homeManage")
 	public Result<Map<String, List<HomeManagementFrontView>>> getPcHomeManagementFrontPage() {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "pc:homeManage";
+		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "pc:homeManage";
 		//移除奈飞客厅 临时
 		Long filterConfigId = null;
 //		if (isHzIp()) {
@@ -1154,7 +1154,7 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/pc/realGoodsConfig")
 	public Result<? extends Object> getPcRealGoodsConfig() throws Exception {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "pc:realHomePage";
+		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "pc:realHomePage";
 		Object o = redisService.get(key);
 		List<HomeManagementFrontView> list = null;
 		if (o == null) {
@@ -1173,7 +1173,7 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/subsidy")
 	public Result<List<GoodsDonSkuSubsidyFrontView>> getSubsidyGoods() {
-		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "subsidy";
+		String key = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "subsidy";
 		Object o = redisService.get(key);
 		if (o == null) {
 			List<GoodsDonSkuSubsidyFrontView> subsidyList = beanSearcher.searchAll(GoodsDonSkuSubsidyFrontView.class, MapUtils.builder().build());
@@ -1210,7 +1210,7 @@ public class GoodsDonController {
 	 */
 	@GetMapping("/get/subsidy/detail/{id}")
 	public Result<GoodsDonSubsidyDetailView> getSubsidyDetailById(@PathVariable Long id) throws Exception {
-		String goodsDetailKey = RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "subsidy:detail:" + id;
+		String goodsDetailKey = RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "subsidy:detail:" + id;
 		Object o = redisService.get(goodsDetailKey);
 		GoodsDonSubsidyDetailView subsidyDetail = null;
 		if (o == null) {

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

@@ -47,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;
@@ -60,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;
 
 /**
@@ -126,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")
@@ -287,7 +295,7 @@ public class GroupRelationController {
             if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限");
         }
         //一分钟内 只能一人获取
-        boolean b = redisService.setNx(RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getEnvName() + groupsRelationView.getTripsAccount(), relationId, RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getTimeout());
+        boolean b = redisService.setNx(RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getName() + groupsRelationView.getTripsAccount(), relationId, RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getTimeout());
         if (!b) {
             throw BusinessRuntimeException.getInstance("一分钟内已有人获取该账号验证码,请稍后获取..");
         }
@@ -874,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);
+    }
 }

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/information/InformationController.java

@@ -63,7 +63,7 @@ public class InformationController {
      */
     @GetMapping("/get/detail/{id}")
     public Result<InformationDetailView> getInformation(@PathVariable Long id) {
-        String key = RedisService.key.INFORMATION_KEY.getEnvName() + "id:" + id;
+        String key = RedisService.key.INFORMATION_KEY.getName() + "id:" + id;
         InformationDetailView view = (InformationDetailView) redisService.get(key);
         if (view == null){
             view = beanSearcher.searchFirst(InformationDetailView.class, MapUtils.flatBuilder(request.getParameterMap())

+ 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);
 		}
@@ -1058,4 +1068,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();
+	}
 }

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

@@ -28,7 +28,7 @@ import com.cyksj.model.views.GroupsRelationIndependentView;
 import com.cyksj.model.views.GroupsRelationRechargeView;
 import com.cyksj.model.views.OrderDonRenewView;
 import com.cyksj.service.relation.GroupRelationClearService;
-import com.cyksj.service.scheduler.SchedulerService;
+
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
@@ -57,7 +57,7 @@ public class CmsGroupRelationController {
 
     private final HttpServletRequest request;
 
-    private final SchedulerService schedulerService;
+    //private final SchedulerService schedulerService;
 
     private final GroupsRelationMapper groupsRelationMapper;
 
@@ -86,7 +86,7 @@ public class CmsGroupRelationController {
     @PutMapping("/disable/{groupsId}")
     @NoSubmit
     public Result<String> disable(@PathVariable Long groupsId) {
-        schedulerService.assignUserGroupsRelation(groupsId);
+        //schedulerService.assignUserGroupsRelation(groupsId);
         return GatewayResponse.SUCCESS.newBuilder().toResult("车队账号禁用成功");
     }
 

+ 1 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/home/HomeManageConfigController.java

@@ -49,6 +49,7 @@ public class HomeManageConfigController {
 	@PostMapping("/post")
 	public Result<String> saveConfig(@RequestBody HomeManageConfigReq config) {
 		homeManagementConfigService.saveOrUpdateConfig(config);
+		refreshCacheService.refreshYhHomePageCache();
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 

+ 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);
+	}
+}

+ 102 - 73
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MidjourneyController.java

@@ -3,7 +3,9 @@ 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;
@@ -12,8 +14,11 @@ 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;
@@ -28,6 +33,8 @@ 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;
 
@@ -54,46 +61,28 @@ public class MidjourneyController {
     private final GroupsRelationMapper groupsRelationMapper;
 
     private final MidjourneyPaintingPlazaMapper midjourneyPaintingPlazaMapper;
+
     public MidjourneyUser getUser(){
         String userToken = request.getHeader("user-token");
-        MidjourneyUser midjourneyUser = (MidjourneyUser) redisService.get(RedisService.key.MIDJOURNEY_USER.getName() + userToken);
+
+        MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
+                .eq(MidjourneyUser::getUserToken, userToken).last("limit 1"));
         if (midjourneyUser == null){
-            midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class)
-                    .eq(MidjourneyUser::getUserToken, userToken).last("limit 1"));
-            if (midjourneyUser == null){
-                throw new BusinessRuntimeException("账号不存在,请重新登录");
-            }
-            Long relationId = midjourneyUser.getRelationId();
-            GroupsRelation relation = groupsRelationMapper.selectById(relationId);
-            midjourneyUser.setAqType(relation.getAqType());
-            redisService.set(RedisService.key.MIDJOURNEY_USER.getName() + userToken, midjourneyUser, RedisService.key.MIDJOURNEY_USER.getTimeout());
-            Object fastNum = redisService.get(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId());
-            if (fastNum == null){
-                redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
-            }
-            Object relaxNum = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId());
-            if (relaxNum == null){
-                if (midjourneyUser.getMjRelaxNum() != null){
-                    redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
-                }
-            }
-        }else {
-            Object fastNum = redisService.get(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId());
-            if (fastNum == null){
-                redisService.set(RedisService.key.MIDJOURNEY_FAST_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjFastNum(), RedisService.key.MIDJOURNEY_FAST_LIMIT.getTimeout());
-            }else {
-                midjourneyUser.setMjFastNum(Integer.parseInt(fastNum.toString()));
-            }
-            Object relaxNum = redisService.get(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId());
-            if (relaxNum == null){
-                if (midjourneyUser.getMjRelaxNum() != null){
-                    redisService.set(RedisService.key.MIDJOURNEY_RELAX_LIMIT.getName() + midjourneyUser.getId(), midjourneyUser.getMjRelaxNum(), RedisService.key.MIDJOURNEY_RELAX_LIMIT.getTimeout());
-                }
-            }else {
-                midjourneyUser.setMjRelaxNum(Integer.parseInt(relaxNum.toString()));
-            }
+            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;
+
     }
 
 
@@ -106,18 +95,35 @@ public class MidjourneyController {
             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;
@@ -132,32 +138,34 @@ public class MidjourneyController {
     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);
-    }
+    ///**
+    // * 同步数据库
+    // */
+    //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);
+    //}
 
 
     /**
@@ -174,8 +182,9 @@ public class MidjourneyController {
      * 提交Imagine任务
      */
     @PostMapping("/submit/imagine")
+    @NoSubmit
     public Result<MidjourneyUserConversation> submitImagine(@RequestBody SubmitImagineDTO submitImagineDTO) {
-        log.info("提交Imagine任务,提示:{},base64数组长度:{}",submitImagineDTO.getPrompt(),submitImagineDTO.getBase64Array());
+        log.info("提交Imagine任务,提示:{}",submitImagineDTO.getPrompt());
         MidjourneyUser user = getUser();
         Long num = checkUserLimit(user);
         if (num != null && num < 0){
@@ -183,12 +192,12 @@ public class MidjourneyController {
         }
         MidjourneyUserConversation conversation;
         try {
-            conversation = midjourneyService.submitImagine(user, submitImagineDTO.getPrompt(), submitImagineDTO.getBase64Array());
+            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);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -196,6 +205,7 @@ public class MidjourneyController {
      * 提交Describe任务
      */
     @PostMapping("/submit/describe")
+    @NoSubmit
     public Result<MidjourneyUserConversation> submitDescribe(@RequestBody SubmitDescribeDTO submitDescribeDTO) {
         log.info("提交Describe任务");
         MidjourneyUser user = getUser();
@@ -205,12 +215,12 @@ public class MidjourneyController {
         }
         MidjourneyUserConversation conversation;
         try {
-            conversation = midjourneyService.submitDescribe(user, submitDescribeDTO.getBase64());
+            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);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -218,6 +228,7 @@ public class MidjourneyController {
      * 提交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();
@@ -227,12 +238,12 @@ public class MidjourneyController {
         }
         MidjourneyUserConversation conversation;
         try {
-            conversation = midjourneyService.submitBlend(user, submitBlendDTO.getDimensions(), submitBlendDTO.getBase64Array());
+            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);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -240,8 +251,9 @@ public class MidjourneyController {
      * 提交Modal任务
      */
     @PostMapping("/submit/modal")
+    @NoSubmit
     public Result<MidjourneyUserConversation> submitModal(@RequestBody SubmitModalDTO submitModalDTO) {
-        log.info("提交Modal任务,taskId:{},提示:{},base64数组长度:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt(),submitModalDTO.getMaskBase64());
+        log.info("提交Modal任务,taskId:{},提示:{}",submitModalDTO.getTaskId(),submitModalDTO.getPrompt());
         MidjourneyUser user = getUser();
         Long num = checkUserLimit(user);
         if (num != null && num < 0){
@@ -254,7 +266,7 @@ public class MidjourneyController {
             recoverUserLimit(user.getId(), user.getMode(),num);
             throw BusinessRuntimeException.getInstance(e.getMessage());
         }
-        syncUser(user.getId(), user.getMode(), num);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -262,6 +274,7 @@ public class MidjourneyController {
      * 提交Shorten任务
      */
     @PostMapping("/submit/shorten")
+    @NoSubmit
     public Result<MidjourneyUserConversation> submitShorten(@RequestBody SubmitShortenDTO submitShortenDTO) {
         log.info("提交Shorten任务 提示词:{}",submitShortenDTO.getPrompt());
         MidjourneyUser user = getUser();
@@ -271,12 +284,12 @@ public class MidjourneyController {
         }
         MidjourneyUserConversation conversation;
         try {
-            conversation = midjourneyService.submitShorten(user, submitShortenDTO.getPrompt());
+            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);
+        //syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -284,21 +297,24 @@ public class MidjourneyController {
      * 执行动作
      */
     @PostMapping("/submit/action")
-    public Result<MidjourneyUserConversation> action(@RequestBody SubmitActionDTO actionDTO) {
+    @NoSubmit
+    public Result<Object> action(@RequestBody SubmitActionDTO actionDTO) {
         log.info("任务id:{},执行动作:{}",actionDTO.getTaskId(),actionDTO.getCustomId());
         MidjourneyUser user = getUser();
-        Long num = checkUserLimit(user);
-        if (num != null && num < 0){
-            throw BusinessRuntimeException.getInstance("次数已用完");
+        Long num = 0L;
+        if (!actionDTO.getCustomId().contains("BOOKMARK")) {
+            num = checkUserLimit(user);
+            if (num != null && num < 0) {
+                throw BusinessRuntimeException.getInstance("次数已用完");
+            }
         }
-        MidjourneyUserConversation conversation;
+        Object conversation;
         try {
-            conversation = midjourneyService.submitAction(user, actionDTO.getTaskId(), actionDTO.getCustomId());
+            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());
         }
-        syncUser(user.getId(), user.getMode(), num);
         return GatewayResponse.SUCCESS.newBuilder().toResult(conversation);
     }
 
@@ -330,6 +346,7 @@ public class MidjourneyController {
      * 取消任务
      */
     @PostMapping("/conversation/{id}/cancel")
+    @NoSubmit
     public Result<MidjourneyUserConversation> conversationCancel(@PathVariable("id") Long id){
         MidjourneyUser user = getUser();
         log.info("取消任务 id:{}",id);
@@ -349,10 +366,22 @@ public class MidjourneyController {
         }
         midjourneyUser.setMode(mode);
         midjourneyUserMapper.updateById(midjourneyUser);
-        redisService.del(RedisService.key.MIDJOURNEY_USER.getName() + midjourneyUser.getUserToken());
+        //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);
+    }
+
+
 
     /**
      * mj绘画广场
@@ -384,7 +413,7 @@ public class MidjourneyController {
         MidjourneyUser user = getUser();
         String condition = String.format(" and mc.user_id = %s", user.getId());
         if (StrUtil.isNotBlank(prompt)) {
-            condition += String.format(" and mc.prompt = '%s'", prompt);
+            condition += String.format(" and mc.prompt like '%%%s%%'", prompt);
         }
         if (bookmark != null) {
             condition += String.format(" and mc.bookmark is %s", bookmark);

+ 68 - 22
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -1,14 +1,16 @@
 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.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;
@@ -37,7 +39,6 @@ import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
-import java.util.Set;
 
 /**
  * /server/镜像服务
@@ -71,6 +72,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 +109,7 @@ 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(user.getRelationId().toString());
             }
         } catch (Exception e) {
             log.error("服务器错误", e);
@@ -152,29 +159,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或4o-mini,预计 " + 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();
@@ -355,4 +376,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();
+    }
 }

+ 58 - 5
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
@@ -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);
+    }
 }

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

@@ -205,7 +205,7 @@ public class SysConfigController {
 	public Result getServiceIndx() {
 		long userId = StpUserUtil.getLoginIdAsLong();
 		long time = DateUtil.beginOfDay(DateTime.now()).getTime();
-		Object re = redisService.get(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getEnvName() + time + userId);
+		Object re = redisService.get(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getName() + time + userId);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(re);
 	}
 
@@ -216,7 +216,7 @@ public class SysConfigController {
 	public Result<Integer> serviceRecord(@PathVariable Long indx) {
 		long userId = StpUserUtil.getLoginIdAsLong();
 		long time = DateUtil.beginOfDay(DateTime.now()).getTime();
-		redisService.set(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getEnvName() + time + userId, indx, RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getTimeout());
+		redisService.set(RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getName() + time + userId, indx, RedisService.key.EQUIPMENT_USER_SERVICE_RECORD.getTimeout());
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netflix-web/src/main/resources/application-dev.yml


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
netflix-web/src/main/resources/application-prd.yml


+ 3 - 2
netflix-web/src/main/resources/application-pre.yml

@@ -139,7 +139,7 @@ wx-login:
   redirectUri: https://nf.video/8082/api/auth/wx/authLogin/baseRedirect
   loginUrl: https://nf.video
   cpsRedirectUri: https://nf.video/8082/api/cps/manage/wx/authLogin/baseRedirect
-  cpsLoginUrl: https://cps.nf.video/yinhe/cps/loginNexte
+  cpsLoginUrl: https://cps.nf.video/yinhe/cps/homePage
   yhShopRedirectUri: https://nf.video/8082/api/yhShop/manage/wx/authLogin/baseRedirect
   yhShopLoginUrl: https://shop.liuliangbang.vip/mall/admin/loginNexte
   baRedirectUrl: https://nf.video/8082/api/applets/market/task/bind/wx/baseRedirect
@@ -197,4 +197,5 @@ smsVerify:
 
 midjourney:
   url: https://nf.video
-  drawUrl: https://nf.video/drawTest/web/
+  drawUrl: https://nf.video/drawTest/web/
+  cdn: https://nf.video

+ 1 - 2
netflix-web/src/main/resources/application.yml

@@ -1,4 +1,3 @@
 spring:
   profiles:
-    active:
-      - ${activeProfile}
+    active: dev

Некоторые файлы не были показаны из-за большого количества измененных файлов