Explorar o código

claude code普通推广

zoujiajian hai 11 meses
pai
achega
b2f5614ad0
Modificáronse 43 ficheiros con 1671 adicións e 69 borrados
  1. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 16 0
      netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeCreditCardMapper.java
  3. 14 0
      netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeDayResetRecordMapper.java
  4. 14 0
      netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeUserCreditCardRecordMapper.java
  5. 14 0
      netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeUserResetRecordMapper.java
  6. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponRecommendMapper.java
  7. 5 0
      netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java
  8. 5 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GzhBodyDto.java
  9. 67 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeCreditCard.java
  10. 28 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeDayResetRecord.java
  11. 20 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeMultiplier.java
  12. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUser.java
  13. 61 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserCreditCardRecord.java
  14. 51 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserResetRecord.java
  15. 6 1
      netflix-dao/src/main/java/com/cyksj/model/entity/RelayServer.java
  16. 26 0
      netflix-dao/src/main/java/com/cyksj/model/request/ClaudeCodeCreditCardUseReq.java
  17. 15 0
      netflix-dao/src/main/java/com/cyksj/model/request/CreditResetReq.java
  18. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/LoginReq.java
  19. 39 0
      netflix-dao/src/main/java/com/cyksj/model/request/TimeRateConfigReq.java
  20. 53 0
      netflix-dao/src/main/java/com/cyksj/model/response/ClaudeCodeRewardDetailsResp.java
  21. 34 0
      netflix-dao/src/main/java/com/cyksj/model/response/CreditResetResp.java
  22. 59 0
      netflix-dao/src/main/java/com/cyksj/model/response/TimeRateConfigResp.java
  23. 16 0
      netflix-dao/src/main/java/com/cyksj/model/response/TimeRateConfigsResp.java
  24. 24 0
      netflix-dao/src/main/java/com/cyksj/model/response/TimeRateCurrentResp.java
  25. 2 0
      netflix-dao/src/main/java/com/cyksj/model/response/claudecode/ClaudeCodeResp.java
  26. 85 0
      netflix-dao/src/main/java/com/cyksj/model/views/CcPromotionInvitationDetailView.java
  27. 72 0
      netflix-dao/src/main/java/com/cyksj/model/views/ClaudeCodeUserCreditCardRecordView.java
  28. 57 0
      netflix-dao/src/main/java/com/cyksj/model/views/ClaudeCodeUserResetRecordView.java
  29. 55 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeWaitingPointsOrderDetailView.java
  30. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuView.java
  31. 10 0
      netflix-dao/src/main/resources/mapper/CouponRecommendMapper.xml
  32. 1 0
      netflix-dao/src/main/resources/mapper/UserDistributeSharedMapper.xml
  33. 61 0
      netflix-service/src/main/java/com/cyksj/service/claude/ClaudeCodeService.java
  34. 475 8
      netflix-service/src/main/java/com/cyksj/service/claude/impl/ClaudeCodeServiceImpl.java
  35. 13 6
      netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java
  36. 1 1
      netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java
  37. 24 1
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  38. 6 2
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
  39. 21 9
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  40. 11 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  41. 3 3
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  42. 174 36
      netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java
  43. 3 2
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

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

@@ -658,4 +658,14 @@ public interface Constant {
 	 * claude code日卡推广活动
 	 * claude code日卡推广活动
 	 */
 	 */
 	Long DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID = 732L;
 	Long DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID = 732L;
+
+	/**
+	 * cc推广标识
+	 */
+	String CC_DISTRIBUTE_MARK = "cc";
+
+	/**
+	 * CLAUDE CODE 积分卡number
+	 */
+	String CLAUDE_CODE_CARD_NUMBER = "CODE_CARD_NUMBER_";
 }
 }

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeCreditCardMapper.java

@@ -0,0 +1,16 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeCreditCard;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCardMapper
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡Mapper
+ */
+@Mapper
+public interface ClaudeCodeCreditCardMapper extends BaseMapper<ClaudeCodeCreditCard> {
+}

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

@@ -0,0 +1,14 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeDayResetRecord;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeDayResetRecordMapper
+ * 创建者: Claude
+ * 创建时间:2025/8/29
+ * 描述: claude code每日重置次数记录Mapper
+ */
+public interface ClaudeCodeDayResetRecordMapper extends BaseMapper<ClaudeCodeDayResetRecord> {
+}

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

@@ -0,0 +1,14 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeUserCreditCardRecord;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserCreditCardRecordMapper
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户积分卡使用记录Mapper
+ */
+public interface ClaudeCodeUserCreditCardRecordMapper extends BaseMapper<ClaudeCodeUserCreditCardRecord> {
+}

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

@@ -0,0 +1,14 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeUserResetRecord;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserResetRecordMapper
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户重置次数记录Mapper
+ */
+public interface ClaudeCodeUserResetRecordMapper extends BaseMapper<ClaudeCodeUserResetRecord> {
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponRecommendMapper.java

@@ -3,6 +3,7 @@ package com.cyksj.mapper.manage.coupon;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.model.entity.Coupon;
 import com.cyksj.model.entity.CouponRecommend;
 import com.cyksj.model.entity.CouponRecommend;
 import com.cyksj.model.views.CouponAvailableRecommendView;
 import com.cyksj.model.views.CouponAvailableRecommendView;
 import com.cyksj.model.views.CouponRecommendView;
 import com.cyksj.model.views.CouponRecommendView;
@@ -29,4 +30,6 @@ public interface CouponRecommendMapper extends BaseMapper<CouponRecommend> {
 	 * 该优惠券是否处于推荐中
 	 * 该优惠券是否处于推荐中
 	 */
 	 */
 	int checkPresentRecommendByCouponId(Long couponId);
 	int checkPresentRecommendByCouponId(Long couponId);
+
+	Coupon getRecommendCouponByGoodsId(Long goodsId);
 }
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java

@@ -89,4 +89,9 @@ public class AuthRedirect {
      * 1.普通店铺(默认) 2.镜像店铺
      * 1.普通店铺(默认) 2.镜像店铺
      */
      */
     private Integer cmt = 1;
     private Integer cmt = 1;
+
+    /**
+     * 是否是cc普通推广
+     */
+    private Boolean cgTj;
 }
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GzhBodyDto.java

@@ -102,4 +102,9 @@ public class GzhBodyDto {
 	 * 1.普通店铺(默认) 2.镜像店铺
 	 * 1.普通店铺(默认) 2.镜像店铺
 	 */
 	 */
 	private Integer cmt = 1;
 	private Integer cmt = 1;
+
+	/**
+	 * 是否是cc普通推广
+	 */
+	private Boolean cgTj;
 }
 }

+ 67 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeCreditCard.java

@@ -0,0 +1,67 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCard
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡定义表
+ */
+@Getter
+@Setter
+public class ClaudeCodeCreditCard extends BaseEntity {
+    
+    /**
+     * 积分卡编号
+     */
+    private String cardNumber;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 首单订单id
+     */
+    private Long orderId;
+    
+    /**
+     * 积分额度
+     */
+    private Integer creditAmount;
+    
+    /**
+     * 积分卡状态 0:未使用 1:已使用 2:已过期
+     */
+    private Integer status;
+    
+    /**
+     * 使用用户ID
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Long usedUserId;
+    
+    /**
+     * 使用时间
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Date usedTime;
+    
+    /**
+     * 有效期
+     */
+    private Date expiryTime;
+    
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeDayResetRecord.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeDayResetRecord
+ * 创建者: Claude
+ * 创建时间:2025/8/29
+ * 描述: claude code每日重置次数记录
+ */
+@Getter
+@Setter
+@TableName("claude_code_day_reset_record")
+public class ClaudeCodeDayResetRecord extends BaseEntity {
+    
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 关联ID
+     */
+    private Long relationId;
+}

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

@@ -0,0 +1,20 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeMultiplier
+ * 创建者: JavaZou
+ * 创建时间:2025/8/26 11:15
+ */
+@Getter
+@Setter
+public class ClaudeCodeMultiplier extends BaseEntity{
+	private String modelName;
+
+	private BigDecimal multiplier;
+}

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

@@ -69,4 +69,10 @@ public class ClaudeCodeUser extends BaseEntity{
 	 * 需要重试 默认false
 	 * 需要重试 默认false
 	 */
 	 */
 	private Boolean isRetry;
 	private Boolean isRetry;
+
+	/**
+	 * 重置次数
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Integer resetCount;
 }
 }

+ 61 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserCreditCardRecord.java

@@ -0,0 +1,61 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserCreditCardRecord
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户积分卡使用记录表
+ */
+@Getter
+@Setter
+public class ClaudeCodeUserCreditCardRecord extends BaseEntity {
+    
+    /**
+     * 用户ID
+     */
+    private Long userId;
+    
+    /**
+     * 使用前积分值
+     */
+    private Integer beforeCodePoints;
+    
+    /**
+     * 增加的积分值
+     */
+    private Integer addCodePoints;
+    
+    /**
+     * 使用后积分值
+     */
+    private Integer afterCodePoints;
+    
+    /**
+     * 积分卡编号/批次号
+     */
+    private String cardNumber;
+    
+    /**
+     * 操作人ID
+     */
+    private Long operatorId;
+    
+    /**
+     * 操作人姓名
+     */
+    private String operatorName;
+    
+    /**
+     * 使用原因
+     */
+    private String useReason;
+
+    /**
+     * 次数
+     */
+    private Integer num;
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserResetRecord.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserResetRecord
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户重置次数记录表
+ */
+@Getter
+@Setter
+public class ClaudeCodeUserResetRecord extends BaseEntity {
+    
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+    
+    /**
+     * 重置前积分值
+     */
+    private Integer beforeCodePoints;
+    
+    /**
+     * 重置后积分值
+     */
+    private Integer afterCodePoints;
+    
+    /**
+     * 重置类型 1:手动重置 2:系统重置
+     */
+    private Integer resetType;
+
+    /**
+     * 正数为加 负数扣除
+     */
+    private Integer num;
+    
+    /**
+     * 重置原因
+     */
+    private String resetReason;
+}

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

@@ -1,6 +1,7 @@
 package com.cyksj.model.entity;
 package com.cyksj.model.entity;
 
 
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Data;
 import lombok.Data;
 
 
 /**
 /**
@@ -8,6 +9,7 @@ import lombok.Data;
  */
  */
 @Data
 @Data
 @TableName("relay_servers")
 @TableName("relay_servers")
+@SearchBean(tables = "relay_servers")
 public class RelayServer extends BaseEntity {
 public class RelayServer extends BaseEntity {
     
     
     private String host;
     private String host;
@@ -15,7 +17,10 @@ public class RelayServer extends BaseEntity {
     private String name;
     private String name;
     
     
     private String region;
     private String region;
-    
+
+    /**
+     * 1-正常 2-维护 0-禁用
+     */
     private Integer status;
     private Integer status;
     
     
     private Integer priority;
     private Integer priority;

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ClaudeCodeCreditCardUseReq.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCardUseReq
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡使用请求
+ */
+@Getter
+@Setter
+public class ClaudeCodeCreditCardUseReq {
+    
+    /**
+     * 积分卡编号
+     */
+    private String cardNumber;
+    
+    /**
+     * 用户ID (由控制器自动设置)
+     */
+    private Long userId;
+}

+ 15 - 0
netflix-dao/src/main/java/com/cyksj/model/request/CreditResetReq.java

@@ -0,0 +1,15 @@
+package com.cyksj.model.request;
+
+import lombok.Data;
+
+import javax.validation.constraints.Size;
+
+/**
+ * 积分重置请求参数
+ */
+@Data
+public class CreditResetReq {
+
+    @Size(max = 500, message = "重置说明最多500个字符")
+    private String description;
+}

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

@@ -74,4 +74,9 @@ public class LoginReq {
 	 * 店铺自定义id
 	 * 店铺自定义id
 	 */
 	 */
 	private String customId;
 	private String customId;
+
+	/**
+	 * 是否是cc普通推广
+	 */
+	private Boolean cgTj;
 }
 }

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/request/TimeRateConfigReq.java

@@ -0,0 +1,39 @@
+package com.cyksj.model.request;
+
+import lombok.Data;
+
+import javax.validation.constraints.*;
+
+/**
+ * 时间倍率配置请求参数
+ */
+@Data
+public class TimeRateConfigReq {
+
+    @NotBlank(message = "配置名称不能为空")
+    @Size(min = 1, max = 100, message = "配置名称长度必须在1-100字符之间")
+    private String name;
+
+    @NotNull(message = "开始小时不能为空")
+    @Min(value = 0, message = "开始小时必须在0-23之间")
+    @Max(value = 23, message = "开始小时必须在0-23之间")
+    private Integer startHour;
+
+    @NotNull(message = "结束小时不能为空")
+    @Min(value = 0, message = "结束小时必须在0-23之间")
+    @Max(value = 23, message = "结束小时必须在0-23之间")
+    private Integer endHour;
+
+    @NotNull(message = "倍率系数不能为空")
+    @DecimalMin(value = "0.001", message = "倍率系数必须在0.001-10.000之间")
+    @DecimalMax(value = "10.000", message = "倍率系数必须在0.001-10.000之间")
+    private Double multiplier;
+
+    @Size(max = 200, message = "配置描述最多200个字符")
+    private String description;
+
+    private Boolean isActive = true;
+
+    @Min(value = 0, message = "优先级必须大于等于0")
+    private Integer priority = 0;
+}

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/response/ClaudeCodeRewardDetailsResp.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeRewardDetailsResp
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode奖励明细响应
+ */
+@Getter
+@Setter
+public class ClaudeCodeRewardDetailsResp {
+    
+    /**
+     * 可用积分卡数量
+     */
+    private Integer availableCreditCards;
+    
+    /**
+     * 用户可重置次数
+     */
+    private Integer resetCount;
+
+    /**
+     * 可提现金额
+     */
+    private BigDecimal gotMoney;
+
+    /**
+     * 带入账金额
+     */
+    private BigDecimal waitingMoney;
+
+    /**
+     * claude code分销比例
+     */
+    private Integer rate;
+
+    /**
+     * 提现门槛金额
+     */
+    private BigDecimal thresholdMoney;
+
+    /**
+     * 每日可重置次数
+     */
+    private Integer dayRestNum = 0;
+}

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/response/CreditResetResp.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.response;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 积分重置响应
+ */
+@Data
+public class CreditResetResp {
+
+    private Long userId;
+    
+    private String description;
+    
+    private CreditStatus beforeReset;
+    
+    private CreditStatus afterReset;
+    
+    private Long creditLimit;
+    
+    private Long restoredCredits;
+    
+    private LocalDateTime resetAt;
+    
+    private String operation = "reset_completed";
+
+    @Data
+    public static class CreditStatus {
+        private Long usedCredits;
+        private Long availableCredits;
+    }
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/response/TimeRateConfigResp.java

@@ -0,0 +1,59 @@
+package com.cyksj.model.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 时间倍率配置响应
+ */
+@Data
+public class TimeRateConfigResp {
+
+    private Long id;
+
+    /**
+     * 配置名称
+     */
+    private String name;
+
+    /**
+     * 开始小时(0-23)
+     */
+    @JsonProperty("start_hour")
+    private Integer startHour;
+
+    /**
+     * 结束小时(0-23)
+     */
+    @JsonProperty("end_hour")
+    private Integer endHour;
+
+    /**
+     * 倍率系数(0.001-10.000)
+     */
+    private Double multiplier;
+
+    /**
+     * 配置描述
+     */
+    private String description;
+
+    /**
+     * 是否启用
+     */
+    @JsonProperty("is_active")
+    private Boolean isActive;
+
+    /**
+     * 优先级(数值越大优先级越高
+     */
+    private Integer priority;
+
+    @JsonProperty("created_at")
+    private Date createdAt;
+
+    @JsonProperty("update_at")
+    private Date updatedAt;
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/response/TimeRateConfigsResp.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.response;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 时间倍率配置列表响应
+ */
+@Data
+public class TimeRateConfigsResp {
+
+    private List<TimeRateConfigResp> configs;
+    
+    private Long total;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/response/TimeRateCurrentResp.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.response;
+
+import lombok.Data;
+
+/**
+ * 当前时间倍率响应
+ */
+@Data
+public class TimeRateCurrentResp {
+
+    /**
+     * 当前小时(0-23)
+     */
+    private Integer currentHour;
+
+    /**
+     * 当前倍率系数
+     */
+    private Double multiplier;
+    
+    private String configName;
+    
+    private String description;
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/response/claudecode/ClaudeCodeResp.java

@@ -17,4 +17,6 @@ public class ClaudeCodeResp {
 	private Integer code;
 	private Integer code;
 
 
 	private String message;
 	private String message;
+
+	private Boolean success;
 }
 }

+ 85 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CcPromotionInvitationDetailView.java

@@ -0,0 +1,85 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.DistributeWaitingSendPoints;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * CC普通推广邀请明细视图
+ */
+@Getter
+@Setter
+@SearchBean(tables = " user_distribute_shared uds INNER JOIN user u ON u.id = uds.user_id" +
+		" LEFT JOIN distribute_waiting_send_points dwsp ON dwsp.user_id = uds.user_id",
+		where = "uds.remark = 'cc'",
+		groupBy = "uds.shared_id,uds.user_id,u.nickname,u.headimgurl,uds.created_time")
+public class CcPromotionInvitationDetailView {
+	/**
+	 * 分销用户id
+	 */
+	@DbField("uds.shared_id")
+	@JsonIgnore
+	private Long sharedId;
+
+	/**
+	 * 被邀请用户ID
+	 */
+	@DbField("uds.user_id")
+	@JsonIgnore
+	private Long userId;
+
+	/**
+	 * 用户昵称
+	 */
+	@DbField("u.nickname")
+	private String nickname;
+
+	/**
+	 * 用户头像
+	 */
+	@DbField("u.headimgurl")
+	private String headimgurl;
+
+	/**
+	 * 提成状态
+	 */
+	@DbIgnore
+	private DistributeWaitingSendPoints.Status status;
+
+	/**
+	 * 首单订单ID
+	 */
+	@DbIgnore
+	private Long firstOrderId;
+
+	/**
+	 * 规格
+	 */
+	@DbIgnore
+	private String specVal;
+
+	/**
+	 * 订单金额
+	 */
+	@DbIgnore
+	private BigDecimal orderMoney;
+
+	/**
+	 * 返现提成
+	 */
+	@DbIgnore
+	private BigDecimal reMoney = BigDecimal.ZERO;
+
+	/**
+	 * 邀请时间
+	 */
+	@DbField("ifnull(max(dwsp.update_time),uds.created_time)")
+	private Date updateTime;
+}

+ 72 - 0
netflix-dao/src/main/java/com/cyksj/model/views/ClaudeCodeUserCreditCardRecordView.java

@@ -0,0 +1,72 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserCreditCardRecordView
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户积分卡使用记录视图
+ */
+@Getter
+@Setter
+@SearchBean(tables = "claude_code_user_credit_card_record")
+public class ClaudeCodeUserCreditCardRecordView {
+    
+    @DbField
+    private Long id;
+    
+    /**
+     * 用户ID
+     */
+    @DbField
+    private Long userId;
+    
+    /**
+     * 使用前积分值
+     */
+    @DbField
+    private Integer beforeCodePoints;
+    
+    /**
+     * 增加的积分值
+     */
+    @DbField
+    private Integer addCodePoints;
+    
+    /**
+     * 使用后积分值
+     */
+    @DbField
+    private Integer afterCodePoints;
+    
+    /**
+     * 积分卡编号/批次号
+     */
+    @DbField
+    private String cardNumber;
+
+    /**
+     * 次数
+     */
+    @DbField
+    private Integer num;
+
+    /**
+     * 使用原因
+     */
+    @DbField
+    private String useReason;
+    
+    /**
+     * 创建时间
+     */
+    @DbField
+    private Date createdTime;
+}

+ 57 - 0
netflix-dao/src/main/java/com/cyksj/model/views/ClaudeCodeUserResetRecordView.java

@@ -0,0 +1,57 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserResetRecordView
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode用户重置记录视图
+ */
+@Getter
+@Setter
+@SearchBean(tables = "claude_code_user_reset_record")
+public class ClaudeCodeUserResetRecordView {
+    
+    @DbField
+    private Long id;
+    
+    /**
+     * 用户ID
+     */
+    @DbField
+    private Long userId;
+    
+    /**
+     * 重置前积分值
+     */
+    @DbField
+    private Integer beforeCodePoints;
+    
+    /**
+     * 重置后积分值
+     */
+    @DbField
+    private Integer afterCodePoints;
+
+    @DbField
+    private Integer num;
+    
+    /**
+     * 重置原因
+     */
+    @DbField
+    private String resetReason;
+    
+    /**
+     * 创建时间
+     */
+    @DbField
+    private Date createdTime;
+}

+ 55 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeWaitingPointsOrderDetailView.java

@@ -0,0 +1,55 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.DistributeWaitingSendPoints;
+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;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: DistributeWaitingPointsOrderDetailView
+ * 创建者: JavaZou
+ * 创建时间:2025/8/27 11:20
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select * from distribute_waiting_send_points where user_id = :uid:) dw" +
+		" inner join order_don o on o.id = dw.order_id" +
+		" left join goods_don_sku sku on sku.id = o.sku_id")
+public class DistributeWaitingPointsOrderDetailView {
+
+	@DbField("dw.user_id")
+	@JsonIgnore
+	private Long userId;
+
+	/**
+	 * 首单订单ID
+	 */
+	@DbField("dw.order_id")
+	private Long orderId;
+
+	/**
+	 * 规格
+	 */
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	/**
+	 * 订单金额
+	 */
+	@DbField("o.money")
+	private BigDecimal orderMoney;
+
+	@DbField("dw.send_status")
+	private DistributeWaitingSendPoints.Status status;
+
+	/**
+	 * 返现提成
+	 */
+	@DbField("TRUNCATE(dw.points/1000,2)")
+	private BigDecimal reMoney = BigDecimal.ZERO;
+}

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

@@ -80,6 +80,12 @@ public class GoodsDonSkuView {
 	@DbField("gdk.code_credit_recovery")
 	@DbField("gdk.code_credit_recovery")
 	private Integer codeCreditRecovery;
 	private Integer codeCreditRecovery;
 
 
+	/**
+	 * 优惠券id
+	 */
+	@DbIgnore
+	private Long couponId;
+
 	/**
 	/**
 	 * 优惠价格
 	 * 优惠价格
 	 */
 	 */

+ 10 - 0
netflix-dao/src/main/resources/mapper/CouponRecommendMapper.xml

@@ -69,4 +69,14 @@
           and (cr.up_time is null or cr.up_time &lt;= now())
           and (cr.up_time is null or cr.up_time &lt;= now())
           and (cr.down_time is null or cr.down_time > now())
           and (cr.down_time is null or cr.down_time > now())
     </select>
     </select>
+
+    <select id="getRecommendCouponByGoodsId" resultType="com.cyksj.model.entity.Coupon">
+        select c.*
+        from coupon_recommend cr inner join coupon c on c.id = cr.coupon_id
+        where cr.deleted is true and c.deleted is true and cr.status is true
+        and (cr.up_time is null or cr.up_time &lt;= now()) and (cr.down_time is null or cr.down_time > now())
+        and (select count(1) from coupon_sku cs where cs.coupon_id = cr.coupon_id and cs.goods_id = #{goodsId}) > 0
+        order by c.discount asc,c.reduce_money desc
+        limit 1
+    </select>
 </mapper>
 </mapper>

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

@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?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">
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper">
 <mapper namespace="com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper">
+
 </mapper>
 </mapper>

+ 61 - 0
netflix-service/src/main/java/com/cyksj/service/claude/ClaudeCodeService.java

@@ -4,11 +4,19 @@ import com.cyksj.model.entity.ClaudeCodeUser;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
+import com.cyksj.model.request.ClaudeCodeCreditCardUseReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
+import com.cyksj.model.request.CreditResetReq;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
+import com.cyksj.model.response.ClaudeCodeRewardDetailsResp;
+import com.cyksj.model.response.CreditResetResp;
+import com.cyksj.model.response.TimeRateConfigsResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
+import com.cyksj.model.views.ClaudeCodeUserCreditCardRecordView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
+import com.cyksj.model.views.ClaudeCodeUserResetRecordView;
+import com.ejlchina.searcher.SearchResult;
 
 
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
@@ -66,4 +74,57 @@ public interface ClaudeCodeService {
 	 * 处理续费升级 TODO
 	 * 处理续费升级 TODO
 	 */
 	 */
 	void handleClaudeCodeUserPackageSku(GroupsRelation relation, GoodsDonSku sku, Long orderId);
 	void handleClaudeCodeUserPackageSku(GroupsRelation relation, GoodsDonSku sku, Long orderId);
+
+	/**
+	 * 获取系统中所有的时间倍率配置列表(包括已启用和已禁用的配置)
+	 */
+	TimeRateConfigsResp getAllConfigs();
+
+	/**
+	 * 将指定用户的积分重置为满积分状态(used_credits设为0)
+	 */
+	CreditResetResp resetUserCredits(Long userId, CreditResetReq req) throws Exception;
+
+	/**
+	 * 重置用户codePoints到原始值并记录重置次数
+	 */
+	void resetUserCodePoints(Long userId, Integer resetType, String resetReason);
+
+	/**
+	 * 用户使用重置次数
+	 */
+	void useResetCount(Long userId) throws Exception;
+
+	/**
+	 * 用户使用积分卡
+	 */
+	void useCreditCard(ClaudeCodeCreditCardUseReq req) throws Exception;
+
+	/**
+	 * 获取用户重置次数明细
+	 */
+	SearchResult<ClaudeCodeUserResetRecordView> getUserResetRecords(Long userId, Integer page, Integer limit);
+
+	/**
+	 * 获取用户积分卡使用明细
+	 */
+	SearchResult<ClaudeCodeUserCreditCardRecordView> getUserCreditCardRecords(Long userId, Integer page, Integer limit);
+
+	/**
+	 * 获取用户奖励明细
+	 */
+	ClaudeCodeRewardDetailsResp getUserRewardDetails(Long userId, Boolean general);
+
+	/**
+	 * 发送积分卡
+	 */
+	void sendCreditCard(Long orderId, Long userId, Integer points, String cardNumber, String remark);
+
+	/**
+	 * 增加或修改用户重置次数
+	 * num为正增加 负扣除
+	 */
+	void adjUserRestNum(Long orderId, Long userId, Integer num, String remark);
+
+	void useDayResetCount(Long userId) throws Exception;
 }
 }

+ 475 - 8
netflix-service/src/main/java/com/cyksj/service/claude/impl/ClaudeCodeServiceImpl.java

@@ -8,23 +8,39 @@ import cn.hutool.http.HttpException;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.http.Method;
 import cn.hutool.http.Method;
+import cn.hutool.json.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.claudecode.ClaudeCodeCreditCardMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeDayResetRecordMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeUserCreditCardRecordMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeUserResetRecordMapper;
+import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
+import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
+import com.cyksj.model.request.ClaudeCodeCreditCardUseReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
+import com.cyksj.model.request.CreditResetReq;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
+import com.cyksj.model.response.ClaudeCodeRewardDetailsResp;
+import com.cyksj.model.response.CreditResetResp;
+import com.cyksj.model.response.TimeRateConfigsResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
+import com.cyksj.model.views.ClaudeCodeUserCreditCardRecordView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
+import com.cyksj.model.views.ClaudeCodeUserResetRecordView;
+import com.cyksj.redis.RedisService;
 import com.cyksj.service.claude.ClaudeCodeService;
 import com.cyksj.service.claude.ClaudeCodeService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import com.ejlchina.searcher.util.MapUtils;
 import com.github.rholder.retry.*;
 import com.github.rholder.retry.*;
@@ -32,11 +48,11 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 
 
@@ -66,8 +82,28 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 
 
 	private final OrderDonMapper orderDonMapper;
 	private final OrderDonMapper orderDonMapper;
 
 
+	private final ClaudeCodeUserResetRecordMapper claudeCodeUserResetRecordMapper;
+
+	private final ClaudeCodeUserCreditCardRecordMapper claudeCodeUserCreditCardRecordMapper;
+
+	private final ClaudeCodeCreditCardMapper claudeCodeCreditCardMapper;
+
+	private final UserMapper userMapper;
+
+	private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
+
+	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final ClaudeCodeDayResetRecordMapper claudeCodeDayResetRecordMapper;
+
+	private final RedisService redisService;
+
 	private final static String CLAUDE_CODE_API_PREFIX = "https://relay01.yhlxj.com/";
 	private final static String CLAUDE_CODE_API_PREFIX = "https://relay01.yhlxj.com/";
 
 
+	public static final String CLAUDE_CODE_HEARD_KEY = "X-Admin-Key";
+
 	public static final String CLAUDE_CODE_API_ADMIN_KEY = "claudecodeyhlxjclaude";
 	public static final String CLAUDE_CODE_API_ADMIN_KEY = "claudecodeyhlxjclaude";
 
 
 	//连接超时时间 毫秒
 	//连接超时时间 毫秒
@@ -188,7 +224,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		if (checkClaudeCodeUser(userId)) {
 		if (checkClaudeCodeUser(userId)) {
 			Long claudeCodeUserId = getClaudeCodeUserId(userId);
 			Long claudeCodeUserId = getClaudeCodeUserId(userId);
 			String url = String.format(CLAUDE_CODE_API_PREFIX + "api/keys/%s/%s", claudeCodeUserId, keyId);
 			String url = String.format(CLAUDE_CODE_API_PREFIX + "api/keys/%s/%s", claudeCodeUserId, keyId);
-			HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header("X-Admin-Key", CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
+			HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
 			String responseBody = execute.body();
 			String responseBody = execute.body();
 			ClaudeCodeResp claudeCodeResp = Jsons.parseObject(responseBody, ClaudeCodeResp.class);
 			ClaudeCodeResp claudeCodeResp = Jsons.parseObject(responseBody, ClaudeCodeResp.class);
 			if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
 			if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
@@ -410,6 +446,48 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		generateOrUpdateClaudeCodeUserInfo(orderId, relation.getId(), relation.getUserId(), sku, 2);
 		generateOrUpdateClaudeCodeUserInfo(orderId, relation.getId(), relation.getUserId(), sku, 2);
 	}
 	}
 
 
+	@Override
+	public TimeRateConfigsResp getAllConfigs() {
+		try {
+			String url = CLAUDE_CODE_API_PREFIX + "api/time-multiplier/configs";
+			ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
+			return Jsons.parseObject(claudeCodeResp.getData(), TimeRateConfigsResp.class);
+		} catch (Exception e) {
+			log.error("获取时间倍率配置列表失败", e);
+			throw BusinessRuntimeException.getInstance("获取时间倍率配置列表失败");
+		}
+	}
+
+	@Override
+	public CreditResetResp resetUserCredits(Long userId, CreditResetReq req) throws Exception {
+		if (userId <= 0) {
+			throw BusinessRuntimeException.getInstance("用户ID无效");
+		}
+
+		String url = CLAUDE_CODE_API_PREFIX + "api/users/" + userId + "/credits/reset";
+		String body = req != null ? Jsons.toJson(req) : "{}";
+		ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(url, body);
+		if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
+			throw BusinessRuntimeException.getInstance("重置次数失败");
+		}
+		return Jsons.parseObject(claudeCodeResp.getData(), CreditResetResp.class);
+	}
+
+	/**
+	 * 验证时间范围
+	 */
+	private void validateTimeRange(Integer startHour, Integer endHour) {
+		if (startHour == null || endHour == null) {
+			throw BusinessRuntimeException.getInstance("开始和结束小时不能为空");
+		}
+		if (startHour < 0 || startHour > 23) {
+			throw BusinessRuntimeException.getInstance("开始小时必须在0-23之间");
+		}
+		if (endHour < 0 || endHour > 23) {
+			throw BusinessRuntimeException.getInstance("结束小时必须在0-23之间");
+		}
+	}
+
 	/**
 	/**
 	 * 获取claude code用户id
 	 * 获取claude code用户id
 	 */
 	 */
@@ -435,7 +513,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 			return build.call(() -> {
 			return build.call(() -> {
 				try {
 				try {
 					HttpResponse execute = HttpUtil.createGet(url)
 					HttpResponse execute = HttpUtil.createGet(url)
-							.header("X-Admin-Key", CLAUDE_CODE_API_ADMIN_KEY)
+							.header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY)
 							.setConnectionTimeout(CONNECT_MILLISECONDS)
 							.setConnectionTimeout(CONNECT_MILLISECONDS)
 							.execute();
 							.execute();
 					ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
 					ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
@@ -463,7 +541,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 			return build.call(() -> {
 			return build.call(() -> {
 				try {
 				try {
 					HttpResponse execute = HttpUtil.createPost(url)
 					HttpResponse execute = HttpUtil.createPost(url)
-							.header("X-Admin-Key", CLAUDE_CODE_API_ADMIN_KEY)
+							.header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY)
 							.setConnectionTimeout(CONNECT_MILLISECONDS)
 							.setConnectionTimeout(CONNECT_MILLISECONDS)
 							.body(body)
 							.body(body)
 							.execute();
 							.execute();
@@ -490,7 +568,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		try {
 		try {
 			return build.call(() -> {
 			return build.call(() -> {
 				try {
 				try {
-					HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header("X-Admin-Key", CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
+					HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
 					ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
 					ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
 					if (!Constant.SUCCESS.equals(resp.getMessage())) {
 					if (!Constant.SUCCESS.equals(resp.getMessage())) {
 						log.info("claude code DELETE URL:{}接口返回msg:{}", url, resp.getMessage());
 						log.info("claude code DELETE URL:{}接口返回msg:{}", url, resp.getMessage());
@@ -543,4 +621,393 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		return build;
 		return build;
 	}
 	}
 
 
+	@Override
+	public void resetUserCodePoints(Long userId, Integer resetType, String resetReason) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+			Wrappers.<ClaudeCodeUser>lambdaQuery().in(ClaudeCodeUser::getUserId, userIdList)
+		);
+
+		if (claudeCodeUser == null) {
+			throw new BusinessRuntimeException("用户不存在或未开通Claude Code服务");
+		}
+
+		Integer beforeCodePoints = claudeCodeUser.getCodePoints();
+		Integer afterCodePoints = claudeCodeUser.getOriCodePoints();
+
+		claudeCodeUser.setCodePoints(afterCodePoints);
+		claudeCodeUserMapper.updateById(claudeCodeUser);
+
+		ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
+		resetRecord.setUserId(userId);
+		resetRecord.setBeforeCodePoints(beforeCodePoints);
+		resetRecord.setAfterCodePoints(afterCodePoints);
+		resetRecord.setResetType(resetType);
+		resetRecord.setResetReason(resetReason);
+
+		claudeCodeUserResetRecordMapper.insert(resetRecord);
+		
+		log.info("用户{}的积分已重置", userId);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void useResetCount(Long userId) throws Exception {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+			Wrappers.lambdaQuery(ClaudeCodeUser.class)
+				.in(ClaudeCodeUser::getUserId, userIdList)
+				.last("limit 1")
+		);
+
+		if (claudeCodeUser == null) {
+			throw new BusinessRuntimeException("用户未开通Claude Code服务");
+		}
+
+		Integer currentResetCount = claudeCodeUser.getResetCount();
+		if (currentResetCount == null || currentResetCount <= 0) {
+			throw BusinessRuntimeException.getInstance("可用重置次数为0");
+		}
+
+		claudeCodeUser.setResetCount(currentResetCount - 1);
+		int updateResult = claudeCodeUserMapper.update(claudeCodeUser,
+				Wrappers.lambdaUpdate(ClaudeCodeUser.class)
+						.eq(ClaudeCodeUser::getId, claudeCodeUser.getId())
+						.eq(ClaudeCodeUser::getResetCount, currentResetCount)
+		);
+
+		if (updateResult > 0) {
+			log.info("用户{}成功使用重置次数,剩余次数:{}", userId, currentResetCount - 1);
+			//重置用户次数
+			CreditResetReq creditResetReq = new CreditResetReq();
+			creditResetReq.setDescription("用户使用重置次数");
+			//调用API重置用户次数
+			resetUserCredits(claudeCodeUser.getUserId(), creditResetReq);
+
+			ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
+			resetRecord.setUserId(userId);
+			resetRecord.setNum(-1);
+			resetRecord.setResetReason("使用重置次数");
+			claudeCodeUserResetRecordMapper.insert(resetRecord);
+
+		} else {
+			throw BusinessRuntimeException.getInstance("使用重置次数失败");
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void useCreditCard(ClaudeCodeCreditCardUseReq req) throws Exception {
+		Long userId = req.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+				Wrappers.lambdaQuery(ClaudeCodeUser.class)
+						.in(ClaudeCodeUser::getUserId, userIdList)
+						.last("limit 1")
+		);
+
+		if (claudeCodeUser == null) {
+			throw new BusinessRuntimeException("用户未开通Claude Code服务");
+		}
+
+		ClaudeCodeCreditCard creditCard = claudeCodeCreditCardMapper.selectOne(
+				Wrappers.lambdaQuery(ClaudeCodeCreditCard.class)
+						.eq(ClaudeCodeCreditCard::getStatus, 0)
+						.in(ClaudeCodeCreditCard::getUserId, userIdList)
+						.last("limit 1")
+		);
+
+		if (creditCard == null) {
+			throw new BusinessRuntimeException("无可用积分卡");
+		}
+
+		if (creditCard.getStatus() != 0) {
+			if (creditCard.getStatus() == 1) {
+				throw new BusinessRuntimeException("积分卡已被使用");
+			} else if (creditCard.getStatus() == 2) {
+				throw new BusinessRuntimeException("积分卡已过期");
+			} else {
+				throw new BusinessRuntimeException("积分卡状态异常");
+			}
+		}
+		String cardNumber = creditCard.getCardNumber();
+
+		if (creditCard.getExpiryTime() != null && creditCard.getExpiryTime().before(new Date())) {
+			creditCard.setStatus(2);
+			claudeCodeCreditCardMapper.updateById(creditCard);
+			throw new BusinessRuntimeException("积分卡已过期");
+		}
+
+		ClaudeCodeResp userBalance = getUserBalance(userId);
+		JSONObject data = Jsons.parseObject(userBalance.getData(), JSONObject.class);
+		Integer availableCredits = data.getInt("available_credits");
+		Integer creditLimit = data.getInt("credit_limit");
+		//超出积分 异常
+		if (availableCredits + creditCard.getCreditAmount() > creditLimit) {
+			throw BusinessRuntimeException.getInstance("目前使用只能补充到{0},建议您消耗更多积分后再兑换使用", creditLimit);
+		}
+
+		Integer beforeCodePoints = availableCredits;
+		Integer addCodePoints = creditCard.getCreditAmount();
+		Integer afterCodePoints = beforeCodePoints + addCodePoints;
+
+		creditCard.setStatus(1);
+		creditCard.setUsedUserId(userId);
+		creditCard.setUsedTime(new Date());
+		creditCard.setRemark("使用积分卡");
+		int cardUpdateResult = claudeCodeCreditCardMapper.update(creditCard,
+				Wrappers.lambdaUpdate(ClaudeCodeCreditCard.class)
+						.eq(ClaudeCodeCreditCard::getId, creditCard.getId())
+						.eq(ClaudeCodeCreditCard::getStatus, 0)
+		);
+
+		if (cardUpdateResult > 0) {
+			ClaudeCodeUserCreditCardRecord creditCardRecord = new ClaudeCodeUserCreditCardRecord();
+			creditCardRecord.setUserId(userId);
+			creditCardRecord.setBeforeCodePoints(beforeCodePoints);
+			creditCardRecord.setAddCodePoints(addCodePoints);
+			creditCardRecord.setAfterCodePoints(afterCodePoints);
+			creditCardRecord.setCardNumber(cardNumber);
+			//使用一次
+			creditCardRecord.setNum(-1);
+			creditCardRecord.setUseReason(creditCard.getRemark());
+
+			claudeCodeUserCreditCardRecordMapper.insert(creditCardRecord);
+
+			log.info("用户{}成功使用积分卡{},增加{}积分", userId, cardNumber, addCodePoints);
+			//调用API调整用户积分
+			adjClaudeCodeUserPoints(claudeCodeUser.getUserId(), creditCard.getCreditAmount(), "adjustment", "用户使用积分卡");
+		} else {
+			throw new BusinessRuntimeException("积分卡使用失败,请重试");
+		}
+	}
+
+	@Override
+	public SearchResult<ClaudeCodeUserResetRecordView> getUserResetRecords(Long userId, Integer page, Integer limit) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		return beanSearcher.search(ClaudeCodeUserResetRecordView.class, MapUtils.builder()
+			.field(ClaudeCodeUserResetRecordView::getUserId, userIdList).op(Operator.InList)
+			.page(page, limit)
+			.orderBy(ClaudeCodeUserResetRecordView::getCreatedTime).desc()
+			.build());
+	}
+
+	@Override
+	public SearchResult<ClaudeCodeUserCreditCardRecordView> getUserCreditCardRecords(Long userId, Integer page, Integer limit) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		return beanSearcher.search(ClaudeCodeUserCreditCardRecordView.class, MapUtils.builder()
+			.field(ClaudeCodeUserCreditCardRecordView::getUserId, userIdList).op(Operator.InList)
+			.page(page, limit)
+			.orderBy(ClaudeCodeUserCreditCardRecordView::getCreatedTime).desc()
+			.build());
+	}
+
+	@Override
+	public ClaudeCodeRewardDetailsResp getUserRewardDetails(Long userId, Boolean general) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		ClaudeCodeRewardDetailsResp response = new ClaudeCodeRewardDetailsResp();
+
+		// 获取用户Claude Code信息
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+				Wrappers.lambdaQuery(ClaudeCodeUser.class)
+						.in(ClaudeCodeUser::getUserId, userIdList)
+						.last("limit 1")
+		);
+
+		// 设置可重置次数
+		if (claudeCodeUser != null) {
+			Integer resetCount = claudeCodeUser.getResetCount();
+			response.setResetCount(resetCount != null ? resetCount : 0);
+		} else {
+			response.setResetCount(0);
+		}
+
+		// 获取可用积分卡数量
+		Integer availableCreditCards = claudeCodeCreditCardMapper.selectCount(
+				Wrappers.lambdaQuery(ClaudeCodeCreditCard.class)
+						.eq(ClaudeCodeCreditCard::getStatus, 0)
+						.in(ClaudeCodeCreditCard::getUserId, userIdList)
+						.isNull(ClaudeCodeCreditCard::getUsedUserId)
+		);
+		response.setAvailableCreditCards(availableCreditCards != null ? availableCreditCards : 0);
+		if (claudeCodeUser.getCodePoints() > 5000) {
+			Integer selectCount = claudeCodeDayResetRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeDayResetRecord.class).in(ClaudeCodeDayResetRecord::getUserId, userIdList).gt(ClaudeCodeDayResetRecord::getCreatedTime, DateUtil.beginOfDay(DateTime.now())));
+			//每日可用重置次数
+			response.setDayRestNum(selectCount > 0 ? 0 : 1);
+		}
+
+		//是否是普通推广
+		if (general != null && general) {
+			//提现门槛
+			DistributePointsExchangeMoney distributePointsExchangeMoney = distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).last("limit 1"));
+			response.setThresholdMoney(BigDecimal.valueOf(distributePointsExchangeMoney.getMinPoints()).divide(BigDecimal.valueOf(distributePointsExchangeMoney.getPoints())).multiply(distributePointsExchangeMoney.getMoney()));
+
+			// 获取分销相关数据
+			try {
+				User user = userMapper.selectById(userId);
+				List<DistributeWaitingSendPoints> distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectList(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getSendStatus, DistributeWaitingSendPoints.Status.waiting).eq(DistributeWaitingSendPoints::getSharedId, userId).select(DistributeWaitingSendPoints::getPoints));
+				BigDecimal waitingPoints = BigDecimal.ZERO;
+				if (!distributeWaitingSendPoints.isEmpty()) {
+					Optional<BigDecimal> points = distributeWaitingSendPoints.stream().map(DistributeWaitingSendPoints::getPoints).reduce(BigDecimal::add);
+					if (points.isPresent()) {
+						waitingPoints = points.get();
+					}
+				}
+				GoodsDon goodsDon = goodsDonMapper.selectById(Constant.CLAUDE_CODE_GOODS_ID);
+				//cc 分销平台比例
+				if (goodsDon != null) {
+					response.setRate(goodsDon.getRate());
+				}
+
+				if (user.getPoints().compareTo(BigDecimal.ZERO) <= 0 && waitingPoints.compareTo(BigDecimal.ZERO) <= 0) {
+					response.setGotMoney(BigDecimal.ZERO);
+					response.setWaitingMoney(BigDecimal.ZERO);
+				} else {
+					BigDecimal points = BigDecimal.valueOf(distributePointsExchangeMoney.getPoints());
+					BigDecimal money = distributePointsExchangeMoney.getMoney();
+					BigDecimal oneHundred = BigDecimal.valueOf(100);
+					if (user.getPoints().compareTo(BigDecimal.ZERO) >= 0) {
+						response.setGotMoney(user.getPoints().divide(points).multiply(money).divide(oneHundred, 2, RoundingMode.HALF_DOWN));
+					}
+					if (user.getPoints().compareTo(BigDecimal.ZERO) >= 0) {
+						response.setWaitingMoney(waitingPoints.divide(points).multiply(money).divide(oneHundred, 2, RoundingMode.DOWN));
+					}
+				}
+
+			} catch (Exception e) {
+				log.warn("获取用户{}分销数据异常", userId, e);
+				// 设置默认值
+				response.setGotMoney(BigDecimal.ZERO);
+				response.setWaitingMoney(BigDecimal.ZERO);
+			}
+		}
+		return response;
+	}
+
+	@Override
+	public void sendCreditCard(Long orderId, Long userId, Integer points, String cardNumber, String remark) {
+		ClaudeCodeCreditCard creditCard = new ClaudeCodeCreditCard();
+		creditCard.setUserId(userId);
+		creditCard.setOrderId(orderId);
+		creditCard.setCardNumber(cardNumber);
+		creditCard.setCreditAmount(points);
+		creditCard.setRemark(remark);
+		claudeCodeCreditCardMapper.insert(creditCard);
+
+		//积分卡明细
+		ClaudeCodeUserCreditCardRecord creditCardRecord = new ClaudeCodeUserCreditCardRecord();
+		creditCardRecord.setUserId(userId);
+		creditCardRecord.setCardNumber(cardNumber);
+		creditCardRecord.setUseReason(remark);
+		creditCardRecord.setNum(1);
+		creditCardRecord.setAddCodePoints(points);
+		claudeCodeUserCreditCardRecordMapper.insert(creditCardRecord);
+	}
+
+	@Override
+	public void adjUserRestNum(Long orderId, Long userId, Integer num, String remark) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		// 获取用户Claude Code信息
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+				Wrappers.lambdaQuery(ClaudeCodeUser.class)
+						.in(ClaudeCodeUser::getUserId, userIdList)
+						.last("limit 1")
+		);
+		if (claudeCodeUser == null) {
+			log.info("claude code user不存在");
+			return;
+		}
+		Integer resetCount = claudeCodeUser.getResetCount();
+		claudeCodeUser.setResetCount(resetCount + num);
+		if (claudeCodeUser.getResetCount() < 0) {
+			return;
+		}
+		int update = 0;
+		while (update == 0) {
+			update = claudeCodeUserMapper.update(claudeCodeUser, Wrappers.lambdaUpdate(ClaudeCodeUser.class).eq(ClaudeCodeUser::getUserId, claudeCodeUser.getUserId()).eq(ClaudeCodeUser::getResetCount, resetCount));
+			if (update == 0) {
+				claudeCodeUser = claudeCodeUserMapper.selectOne(
+						Wrappers.lambdaQuery(ClaudeCodeUser.class)
+								.in(ClaudeCodeUser::getUserId, userIdList)
+								.last("limit 1")
+				);
+				if (claudeCodeUser == null) {
+					break;
+				}
+				resetCount = claudeCodeUser.getResetCount();
+				claudeCodeUser.setResetCount(resetCount + num);
+				if (claudeCodeUser.getResetCount() < 0) {
+					break;
+				}
+			}
+			//记录获取重置次数记录
+			ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
+			resetRecord.setOrderId(orderId);
+			resetRecord.setUserId(userId);
+			resetRecord.setResetReason(remark);
+			resetRecord.setNum(num);
+			claudeCodeUserResetRecordMapper.insert(resetRecord);
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void useDayResetCount(Long userId) throws Exception {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		// 获取用户Claude Code信息
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+				Wrappers.lambdaQuery(ClaudeCodeUser.class)
+						.in(ClaudeCodeUser::getUserId, userIdList)
+						.last("limit 1")
+		);
+		if (claudeCodeUser == null) {
+			log.info("claude code user不存在");
+			return;
+		}
+		//非标准版、专业版 不给使用
+		if (claudeCodeUser.getCodePoints() < 5000) {
+			return;
+		}
+		Integer selectCount = claudeCodeDayResetRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeDayResetRecord.class).in(ClaudeCodeDayResetRecord::getUserId, userIdList).gt(ClaudeCodeDayResetRecord::getCreatedTime, DateUtil.beginOfDay(DateTime.now())));
+		//今日使用为0
+		if (selectCount == 0) {
+			String idxKey = "cc:uid:" + userId;
+			try {
+				if (redisService.setNx(idxKey, userId, 5l)) {
+					//重置用户次数
+					CreditResetReq creditResetReq = new CreditResetReq();
+					creditResetReq.setDescription("用户使用每日重置");
+					//调用API重置用户次数
+					resetUserCredits(claudeCodeUser.getUserId(), creditResetReq);
+
+					ClaudeCodeDayResetRecord claudeCodeDayResetRecord = new ClaudeCodeDayResetRecord();
+					claudeCodeDayResetRecord.setUserId(userId);
+					claudeCodeDayResetRecord.setRelationId(claudeCodeUser.getRelationId());
+					claudeCodeDayResetRecordMapper.insert(claudeCodeDayResetRecord);
+				}
+			} finally {
+				if (redisService.hasKey(idxKey)) {
+					redisService.del(idxKey);
+				}
+			}
+		}
+	}
+
+	private void adjClaudeCodeUserPoints(Long userId, Integer points, String type, String description) throws Exception {
+		String apiKeyUrl = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/credits/adjust", userId);
+		Map<String, Object> parmas = new HashMap<>();
+		parmas.put("amount", points);
+		parmas.put("type", type);
+		parmas.put("description", description);
+		ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(apiKeyUrl, Jsons.toJson(parmas));
+		if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
+			throw BusinessRuntimeException.getInstance("使用积分卡失败");
+		}
+	}
 }
 }

+ 13 - 6
netflix-service/src/main/java/com/cyksj/service/coupon/impl/CouponFontServiceImpl.java

@@ -30,10 +30,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 
 
 /*
 /*
  *项目名: netflix
  *项目名: netflix
@@ -92,7 +89,18 @@ public class CouponFontServiceImpl implements CouponFontService {
 	@Transactional(rollbackFor = Throwable.class)
 	@Transactional(rollbackFor = Throwable.class)
 	public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) {
 	public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) {
 		collectCommonCheck(couponCollectReq.getCouponId(), userId);
 		collectCommonCheck(couponCollectReq.getCouponId(), userId);
-
+		CouponRecommend couponRecommend = recommendMapper.selectOne(Wrappers.lambdaQuery(CouponRecommend.class).eq(CouponRecommend::getCouponId, couponCollectReq.getCouponId()).last("limit 1"));
+		if (couponRecommend == null || !couponRecommend.getDeleted() || !couponRecommend.getStatus()) {
+			return;
+		}
+		Date upTime = couponRecommend.getUpTime();
+		Date downTime = couponRecommend.getDownTime();
+		if (upTime != null && upTime.after(DateTime.now())) {
+			return;
+		}
+		if (downTime != null && downTime.before(DateTime.now())) {
+			return;
+		}
 		receiveCouponUser(couponCollectReq.getCouponId(), userId, CouponUser.Channel.recommend);
 		receiveCouponUser(couponCollectReq.getCouponId(), userId, CouponUser.Channel.recommend);
 	}
 	}
 
 
@@ -360,7 +368,6 @@ public class CouponFontServiceImpl implements CouponFontService {
 			couponUserMapper.insert(couponUser);
 			couponUserMapper.insert(couponUser);
 		} catch (DuplicateKeyException e) {
 		} catch (DuplicateKeyException e) {
 			log.info("用户:{}重复领取优惠券{}插入数据错误", userId, couponId);
 			log.info("用户:{}重复领取优惠券{}插入数据错误", userId, couponId);
-			throw BusinessRuntimeException.getInstance("已领取成功");
 		}
 		}
 	}
 	}
 
 

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

@@ -22,7 +22,7 @@ public interface DistributeService {
 	 * userId: 被邀请人
 	 * userId: 被邀请人
 	 * dsPopularizeId: 后台自定义推广链接id
 	 * dsPopularizeId: 后台自定义推广链接id
 	 */
 	 */
-	void saveDistributionInvitation(Long sharedId, Long userId, Long dsPopularizeId);
+	void saveDistributionInvitation(Long sharedId, Long userId, Long dsPopularizeId, Boolean ccGeneralTg);
 
 
 	/**
 	/**
 	 * 普通推广者绑定优惠推广码
 	 * 普通推广者绑定优惠推广码

+ 24 - 1
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -24,8 +24,10 @@ import com.cyksj.mapper.shop.YhShopUserPlatDistributeRateMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.UserDistributeReq;
 import com.cyksj.model.request.UserDistributeReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.claude.ClaudeCodeService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.market.task.TaskService;
 import com.cyksj.service.market.task.TaskService;
+import com.cyksj.service.relation.GroupRelationFrontService;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.dao.DuplicateKeyException;
@@ -86,8 +88,12 @@ public class DistributeServiceImpl implements DistributeService {
 
 
 	private final DistributeGeneralSkuRateMapper generalSkuRateMapper;
 	private final DistributeGeneralSkuRateMapper generalSkuRateMapper;
 
 
+	private final ClaudeCodeService claudeCodeService;
+
 	private final UserMapper userMapper;
 	private final UserMapper userMapper;
 
 
+	private final GroupRelationFrontService groupRelationFrontService;
+
 	@Override
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	@Transactional(rollbackFor = Throwable.class)
 	public void insertDistribute(UserDistributeReq userDistributeReq) {
 	public void insertDistribute(UserDistributeReq userDistributeReq) {
@@ -317,7 +323,7 @@ public class DistributeServiceImpl implements DistributeService {
 	}
 	}
 
 
 	@Override
 	@Override
-	public void saveDistributionInvitation(Long sharedId, Long userId, Long dsPopularizeId) {
+	public void saveDistributionInvitation(Long sharedId, Long userId, Long dsPopularizeId, Boolean ccGeneralTg) {
 		if (sharedId == 0l || sharedId.equals(userId)) {
 		if (sharedId == 0l || sharedId.equals(userId)) {
 			return;
 			return;
 		}
 		}
@@ -330,8 +336,25 @@ public class DistributeServiceImpl implements DistributeService {
 		//存在分销
 		//存在分销
 		userDistributeShared.setUserId(userId);
 		userDistributeShared.setUserId(userId);
 		userDistributeShared.setDsPopularizeId(dsPopularizeId);
 		userDistributeShared.setDsPopularizeId(dsPopularizeId);
+		if (ccGeneralTg != null) {
+			//普通推广
+			Integer selectCount = userDistributeMapper.selectCount(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, sharedId).eq(UserDistribute::getDeleted, Boolean.TRUE));
+			if (selectCount == 0) {
+				//打上普通cc推广标识
+				userDistributeShared.setRemark(Constant.CC_DISTRIBUTE_MARK);
+			}
+		}
 		try {
 		try {
 			userDistributeSharedMapper.insert(userDistributeShared);
 			userDistributeSharedMapper.insert(userDistributeShared);
+			if (Constant.CC_DISTRIBUTE_MARK.equals(userDistributeShared.getRemark())) {
+				//若是cc普通推广 发送claude code积分卡
+				claudeCodeService.sendCreditCard(null, userDistributeShared.getSharedId(), 1000, Constant.CLAUDE_CODE_CARD_NUMBER + System.currentTimeMillis(), "新用户注册");
+				//存在Claude code车票不发送体验卡
+				if (!claudeCodeService.checkClaudeCodeUser(userId)) {
+					//发送claude code 体验卡
+					groupRelationFrontService.getTrialTicketByUserIdAndGoodsId(userId, Constant.DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID, 1);
+				}
+			}
 			TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
 			TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
 					.eq(TaskType::getName, TaskTypeEnum.share.getDesc()).last("limit 1"));
 					.eq(TaskType::getName, TaskTypeEnum.share.getDesc()).last("limit 1"));
 			taskService.completeTask(taskType, sharedId);
 			taskService.completeTask(taskType, sharedId);

+ 6 - 2
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -176,9 +176,12 @@ public class EventMsgService implements GzhMsgService {
 			userMapper.insert(user);
 			userMapper.insert(user);
 			Long userId = user.getId();
 			Long userId = user.getId();
 			Long dsPopularizeId = null;
 			Long dsPopularizeId = null;
+			Boolean cgTj = null;
 			if (gzhDto != null) {
 			if (gzhDto != null) {
 				Long sharedId = gzhDto.getSharedId();
 				Long sharedId = gzhDto.getSharedId();
 				String dsCode = gzhDto.getDsCode();
 				String dsCode = gzhDto.getDsCode();
+				//是否是cc普通推广
+				cgTj = gzhDto.getCgTj();
 				if (StrUtil.isNotBlank(dsCode)) {
 				if (StrUtil.isNotBlank(dsCode)) {
 					dsCode = dsCode.trim();
 					dsCode = dsCode.trim();
 					User sharedUser = userService.getOne(Wrappers.lambdaQuery(User.class)
 					User sharedUser = userService.getOne(Wrappers.lambdaQuery(User.class)
@@ -197,7 +200,7 @@ public class EventMsgService implements GzhMsgService {
 					}
 					}
 				}
 				}
 				if (sharedId != null) {
 				if (sharedId != null) {
-					distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
+					distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId, cgTj);
 				}
 				}
 				Long popularizeId = gzhDto.getPid();
 				Long popularizeId = gzhDto.getPid();
 				if (popularizeId != null) {
 				if (popularizeId != null) {
@@ -248,6 +251,7 @@ public class EventMsgService implements GzhMsgService {
 			Integer dsType = gzhDto.getDsType();
 			Integer dsType = gzhDto.getDsType();
 			String dsCode = gzhDto.getDsCode();
 			String dsCode = gzhDto.getDsCode();
 			Long dsPopularizeId = null;
 			Long dsPopularizeId = null;
+			Boolean cgTj = gzhDto.getCgTj();
 			if (StrUtil.isNotBlank(dsCode)) {
 			if (StrUtil.isNotBlank(dsCode)) {
 				UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode);
 				UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode);
 				sharedId = userSharedDto.getSharedId();
 				sharedId = userSharedDto.getSharedId();
@@ -260,7 +264,7 @@ public class EventMsgService implements GzhMsgService {
 			//新用户推广
 			//新用户推广
 			if (sharedId != null && isNewUser) {
 			if (sharedId != null && isNewUser) {
 				if (dsType == null || dsType == 1) {
 				if (dsType == null || dsType == 1) {
-					distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
+					distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId, cgTj);
 				}
 				}
 			}
 			}
 			//查找渠道是否有设置了对应的claude code优惠码
 			//查找渠道是否有设置了对应的claude code优惠码

+ 21 - 9
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -28,6 +28,7 @@ import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentReceiveBenefitsRecordMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentReceiveBenefitsRecordMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeUserResetRecordMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeBusinessOrderDonRecordMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeBusinessOrderDonRecordMapper;
@@ -38,7 +39,6 @@ import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubRewardsMapper;
 import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubWaitingMapper;
 import com.cyksj.mapper.manage.distribute.sub.UserDistributeSubWaitingMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderMapper;
 import com.cyksj.mapper.manage.sys.WorkOrderMapper;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopDistributeWaitingSendPointsMapper;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopDistributeWaitingSendPointsMapper;
-import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
 import com.cyksj.mapper.shop.YhShopUserDistributeBusinessOrderDonRecordMapper;
 import com.cyksj.mapper.shop.YhShopUserDistributeBusinessOrderDonRecordMapper;
 import com.cyksj.mapper.stock.GoodsSkuStockRelateMapper;
 import com.cyksj.mapper.stock.GoodsSkuStockRelateMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.entity.*;
@@ -51,6 +51,7 @@ import com.cyksj.model.request.OrderBalanceRefundReq;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.GptUserRechargeRecordService;
 import com.cyksj.service.chatgpt.GptUserRechargeRecordService;
+import com.cyksj.service.claude.ClaudeCodeService;
 import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
@@ -204,16 +205,10 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
 
     private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
     private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
 
 
-    private final OrderDonUpgradeRenewRecordMapper orderDonUpgradeRenewRecordMapper;
-
     private final LumaUserMapper lumaUserMapper;
     private final LumaUserMapper lumaUserMapper;
 
 
-    private final UserBenefitsOrderRecordMapper userBenefitsOrderRecordMapper;
-
     private final UserBenefitsComboRelationRecordMapper userBenefitsComboRelationRecordMapper;
     private final UserBenefitsComboRelationRecordMapper userBenefitsComboRelationRecordMapper;
 
 
-    private final UserMirrorShopMapper userMirrorShopMapper;
-
     private final UserMirrorShopDistributeWaitingSendPointsMapper userMirrorShopDistributeWaitingSendPointsMapper;
     private final UserMirrorShopDistributeWaitingSendPointsMapper userMirrorShopDistributeWaitingSendPointsMapper;
 
 
     private final ClaudeUserMapper claudeUserMapper;
     private final ClaudeUserMapper claudeUserMapper;
@@ -224,12 +219,14 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
 
     private final NetflixUserChangeOtherTicketRecordMapper netflixUserChangeOtherTicketRecordMapper;
     private final NetflixUserChangeOtherTicketRecordMapper netflixUserChangeOtherTicketRecordMapper;
 
 
-    private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
-
     private final UserGalaxyCoinService userGalaxyCoinService;
     private final UserGalaxyCoinService userGalaxyCoinService;
 
 
     private final GptUserRechargeRecordService gptUserRechargeRecordService;
     private final GptUserRechargeRecordService gptUserRechargeRecordService;
 
 
+    private final ClaudeCodeUserResetRecordMapper claudeCodeUserResetRecordMapper;
+
+    private final ClaudeCodeService claudeCodeService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
 
     @Override
     @Override
@@ -1312,6 +1309,21 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         if (orderDon.getGoodsId() == Constant.GPT_PLUS_GID && sku.getNum() == 1) {
         if (orderDon.getGoodsId() == Constant.GPT_PLUS_GID && sku.getNum() == 1) {
             subRechargeNumOrder(orderDon.getUserId(), orderDon.getRelationId(), sku.getMonths(), operator);
             subRechargeNumOrder(orderDon.getUserId(), orderDon.getRelationId(), sku.getMonths(), operator);
         }
         }
+
+        //claude code 退款
+        if (orderDon.getGoodsId() == Constant.CLAUDE_CODE_GOODS_ID) {
+            DistributeWaitingSendPoints distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectOne(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getOrderId, orderDon.getId()).last("limit 1"));
+            if (distributeWaitingSendPoints != null) {
+                if (distributeWaitingSendPoints.getSendStatus() == DistributeWaitingSendPoints.Status.close) {
+                    //是否是普通cc推广
+                    Long orderId = distributeWaitingSendPoints.getOrderId();
+                    ClaudeCodeUserResetRecord claudeCodeUserResetRecord = claudeCodeUserResetRecordMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUserResetRecord.class).eq(ClaudeCodeUserResetRecord::getOrderId, orderId).last("limit 1"));
+                    if (claudeCodeUserResetRecord != null) {
+                        claudeCodeService.adjUserRestNum(orderDon.getId(), distributeWaitingSendPoints.getSharedId(), -1, "新用户订单退款");
+                    }
+                }
+            }
+        }
     }
     }
 
 
     //处理下级渠道分销提成
     //处理下级渠道分销提成

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -2072,6 +2072,17 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 						//给商务人员 分配提成权益
 						//给商务人员 分配提成权益
 						userBusinessFrontService.taskDistributeRateBenefits(userDistributeShared.getSharedId(), businessId, goodsDon.getType(), order, rate);
 						userBusinessFrontService.taskDistributeRateBenefits(userDistributeShared.getSharedId(), businessId, goodsDon.getType(), order, rate);
 					}
 					}
+					//是否是cc普通推广
+					//并且购买claude code作为首单
+					if (userDistribute == null && Constant.CC_DISTRIBUTE_MARK.equals(userDistributeShared.getRemark()) && order.getGoodsId() == Constant.CLAUDE_CODE_GOODS_ID) {
+						//普通推广用户首单,给上级渠道发放 claude code 积分卡
+						try {
+							claudeCodeService.adjUserRestNum(order.getId(), userDistributeShared.getSharedId(), 1, "新用户下单");
+							log.info("用户{}邀请新用户{}首单,发放claude code积分卡成功", userDistributeShared.getSharedId(), order.getUserId());
+						} catch (Exception e) {
+							log.error("给用户{}发放claude code积分卡失败:{}", userDistributeShared.getSharedId(), e.getMessage());
+						}
+					}
 				}
 				}
 			}
 			}
 		}
 		}

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

@@ -228,7 +228,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		}
 		}
 		if (sharedId != null && isNewUser) {
 		if (sharedId != null && isNewUser) {
 			if (dsType == null || dsType == 1) {
 			if (dsType == null || dsType == 1) {
-				distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
+				distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId, re.getCgTj());
 			}
 			}
 		}
 		}
 		//店铺注册用户 关联
 		//店铺注册用户 关联
@@ -554,7 +554,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 			this.save(user);
 			this.save(user);
 			//新用户分销
 			//新用户分销
 			if (sharedId != null) {
 			if (sharedId != null) {
-				distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
+				distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId, loginReq.getCgTj());
 			}
 			}
 			//店铺注册用户 关联
 			//店铺注册用户 关联
 			if (StrUtil.isNotBlank(customId)) {
 			if (StrUtil.isNotBlank(customId)) {
@@ -862,7 +862,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		Long dsPopularizeId = userSharedDto.getDsPopularizeId();
 		Long dsPopularizeId = userSharedDto.getDsPopularizeId();
 		//建立绑定关系
 		//建立绑定关系
 		log.info("建立用户userId:{}与sharedId:{}绑定关系", userId, sharedId);
 		log.info("建立用户userId:{}与sharedId:{}绑定关系", userId, sharedId);
-		distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId);
+		distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId, null);
 	}
 	}
 
 
 	@Override
 	@Override

+ 174 - 36
netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java

@@ -17,9 +17,8 @@ import com.cyksj.mapper.manage.coupon.*;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.manage.views.OrderDonView;
-import com.cyksj.model.request.ClaudeCodeApiKeysReq;
-import com.cyksj.model.request.ClaudeCodeDelReq;
-import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
+import com.cyksj.model.request.*;
+import com.cyksj.model.response.*;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.*;
 import com.cyksj.model.views.*;
 import com.cyksj.service.claude.AnnouncementService;
 import com.cyksj.service.claude.AnnouncementService;
@@ -32,6 +31,7 @@ import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
@@ -394,8 +394,23 @@ public class ClaudeCodeController {
 		}
 		}
 	}
 	}
 
 
+	/**
+	 * 获取中继服务器信息
+	 */
+	@GetMapping("/relays/info")
+	public Result<List<RelayServer>> getRelaysInfo(@RequestParam(required = false) String domain) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		MapBuilder builder = MapUtils.builder();
+		if (StrUtil.isNotBlank(domain)) {
+			builder.field(RelayServer::getHost, domain).op(Operator.Contain);
+		}
+		List<RelayServer> relayServers = beanSearcher.searchAll(RelayServer.class, builder.field(RelayServer::getStatus, 1).onlySelect(RelayServer::getHost, RelayServer::getLatencyMs).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(relayServers);
+	}
+
 	public void setClaudeCodeSkuCouponInfo(String dsCode, Long userId, List<GoodsDonSkuView> goodsDonSkuViews) {
 	public void setClaudeCodeSkuCouponInfo(String dsCode, Long userId, List<GoodsDonSkuView> goodsDonSkuViews) {
 		//渠道推广
 		//渠道推广
+		Coupon coupon = null;
 		if (dsCode != null) {
 		if (dsCode != null) {
 			UserSharedDto popularizeDto = userService.getUserShredDtoByDsCode(dsCode);
 			UserSharedDto popularizeDto = userService.getUserShredDtoByDsCode(dsCode);
 			if (popularizeDto != null) {
 			if (popularizeDto != null) {
@@ -407,41 +422,164 @@ public class ClaudeCodeController {
 							.eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID)
 							.eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID)
 							.eq(CouponDistributePopularize::getDeleted, Boolean.TRUE));
 							.eq(CouponDistributePopularize::getDeleted, Boolean.TRUE));
 					//已配置使用渠道优惠码 未配置使用推荐优惠券
 					//已配置使用渠道优惠码 未配置使用推荐优惠券
-					Coupon coupon = couponMapper.selectById(selectCount > 0 ? Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID : Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
-					if (coupon == null) {
-						return;
-					}
-					if (coupon.getId().intValue() == Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID.intValue()) {
-						int isTj = couponRecommendMapper.checkPresentRecommendByCouponId(Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
-						if (isTj == 0) {
-							return;
-						}
-					}
-					List<Long> couponSkuIds = couponSkuMapper.selectList(Wrappers.lambdaQuery(CouponSku.class).eq(CouponSku::getCouponId, coupon.getId()).eq(CouponSku::getDeleted, Boolean.TRUE)).stream().map(CouponSku::getSkuId).collect(Collectors.toList());
-					//该优惠券是否已经使用
-					if (userId != null) {
-						Integer isUsed = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
-								.eq(CouponUser::getCouponId, coupon.getId())
-								.eq(CouponUser::getStatus, CouponUser.Status.unused)
-								.eq(CouponUser::getUserId, userId)
-								.lt(CouponUser::getValidStartTime, DateTime.now())
-								.gt(CouponUser::getValidEndTime, DateTime.now()));
-						if (isUsed == 0) {
-							return;
-						}
-					}
-					goodsDonSkuViews.forEach(sku -> {
-						if (couponSkuIds.contains(sku.getSkuId())) {
-							if (coupon.getType() == Coupon.Type.discount) {
-								sku.setDiscount(coupon.getDiscount());
-								sku.setDiscountPrice(sku.getMoney().multiply(coupon.getDiscount()));
-							} else {
-								sku.setReduceMoney(coupon.getReduceMoney());
-							}
-						}
-					});
+					coupon = couponMapper.selectById(selectCount > 0 ? Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID : Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
+				}
+			}
+		}
+		Boolean isTjB = false;
+		//非推广链接
+		if (dsCode == null && coupon == null) {
+			coupon = couponRecommendMapper.getRecommendCouponByGoodsId(Constant.CLAUDE_CODE_GOODS_ID);
+			isTjB = true;
+		}
+		if (coupon == null) {
+			return;
+		}
+		if (isTjB || coupon.getId().intValue() == Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID.intValue()) {
+			int isTj = couponRecommendMapper.checkPresentRecommendByCouponId(coupon.getId());
+			if (isTj == 0) {
+				return;
+			}
+		}
+		List<Long> couponSkuIds = couponSkuMapper.selectList(Wrappers.lambdaQuery(CouponSku.class).eq(CouponSku::getCouponId, coupon.getId()).eq(CouponSku::getDeleted, Boolean.TRUE)).stream().map(CouponSku::getSkuId).collect(Collectors.toList());
+		//该优惠券是否已经使用
+		if (userId != null) {
+			Integer selectCount = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class).eq(CouponUser::getCouponId, coupon.getId()).eq(CouponUser::getUserId, userId));
+			if (selectCount > 0) {
+				Integer isUsed = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
+						.eq(CouponUser::getCouponId, coupon.getId())
+						.eq(CouponUser::getStatus, CouponUser.Status.unused)
+						.eq(CouponUser::getUserId, userId)
+						.lt(CouponUser::getValidStartTime, DateTime.now())
+						.gt(CouponUser::getValidEndTime, DateTime.now()));
+				if (isUsed == 0) {
+					return;
 				}
 				}
 			}
 			}
 		}
 		}
+		for (GoodsDonSkuView sku : goodsDonSkuViews) {
+			if (couponSkuIds.contains(sku.getSkuId())) {
+				sku.setCouponId(coupon.getId());
+				if (coupon.getType() == Coupon.Type.discount) {
+					sku.setDiscount(coupon.getDiscount());
+					sku.setDiscountPrice(sku.getMoney().multiply(coupon.getDiscount()));
+				} else {
+					sku.setReduceMoney(coupon.getReduceMoney());
+				}
+			}
+		}
+	}
+
+	//======================================================================时间倍率===============================================================================
+
+	/**
+	 * 获取系统中所有的时间倍率配置列表(包括已启用和已禁用的配置)
+	 */
+	@GetMapping("/timeRate/configs")
+	public Result<TimeRateConfigsResp> getAllConfigs() {
+		TimeRateConfigsResp resp = claudeCodeService.getAllConfigs();
+		if (resp != null && CollUtil.isNotEmpty(resp.getConfigs())) {
+			resp.setConfigs(resp.getConfigs().stream().filter(time -> time.getIsActive()).collect(Collectors.toList()));
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(resp);
+	}
+
+	/**
+	 * claude code模型倍率
+	 */
+	@GetMapping("/get/multiplier")
+	public Result<List<ClaudeCodeMultiplier>> getMultiplier() {
+		List<ClaudeCodeMultiplier> claudeCodeMultipliers = beanSearcher.searchAll(ClaudeCodeMultiplier.class, MapUtils.builder().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(claudeCodeMultipliers);
+	}
+
+	/**
+	 * 用户使用重置次数
+	 */
+	@PostMapping("/use/reset-count")
+	public Result<Map<String, Object>> useResetCount() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		claudeCodeService.useResetCount(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 用户使用每日重置
+	 */
+	@PostMapping("/use/day/reset-count")
+	public Result<Map<String, Object>> useDayResetCount() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		claudeCodeService.useDayResetCount(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 用户使用积分卡
+	 */
+	@PostMapping("/use/credit-card")
+	public Result useCreditCard() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		ClaudeCodeCreditCardUseReq req = new ClaudeCodeCreditCardUseReq();
+		req.setUserId(userId);
+		 claudeCodeService.useCreditCard(req);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+
+	}
+
+	/**
+	 * 获取用户重置次数明细
+	 */
+	@GetMapping("/reset-records")
+	public Result<SearchResult<ClaudeCodeUserResetRecordView>> getUserResetRecords(
+			@RequestParam(defaultValue = "1") Integer page,
+			@RequestParam(defaultValue = "10") Integer limit) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<ClaudeCodeUserResetRecordView> result = claudeCodeService.getUserResetRecords(userId, page, limit);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+	}
+
+	/**
+	 * 获取用户积分卡使用明细
+	 */
+	@GetMapping("/credit-card-records")
+	public Result<SearchResult<ClaudeCodeUserCreditCardRecordView>> getUserCreditCardRecords(
+			@RequestParam(defaultValue = "1") Integer page,
+			@RequestParam(defaultValue = "10") Integer limit) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<ClaudeCodeUserCreditCardRecordView> result = claudeCodeService.getUserCreditCardRecords(userId, page, limit);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+	}
+
+	/**
+	 * 获取用户奖励ino
+	 */
+	@GetMapping("/reward-details")
+	public Result<ClaudeCodeRewardDetailsResp> getUserRewardDetails(Boolean general) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		ClaudeCodeRewardDetailsResp result = claudeCodeService.getUserRewardDetails(userId, general);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+	}
+
+	/**
+	 * CC普通推广邀请明细
+	 */
+	@GetMapping("/get/cc/promotion/invitation/details")
+	public Result<SearchResult<CcPromotionInvitationDetailView>> getCcPromotionInvitationDetails() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<CcPromotionInvitationDetailView> search = beanSearcher.search(CcPromotionInvitationDetailView.class, MapUtils.flatBuilder(request.getParameterMap()).field(CcPromotionInvitationDetailView::getSharedId, userId).orderBy(CcPromotionInvitationDetailView::getUpdateTime).desc().build());
+		search.getDataList().forEach(data -> {
+			DistributeWaitingPointsOrderDetailView detailView = beanSearcher.searchFirst(DistributeWaitingPointsOrderDetailView.class, MapUtils.builder().put("uid", data.getUserId()).field(DistributeWaitingPointsOrderDetailView::getStatus, DistributeWaitingSendPoints.Status.close.name()).op(Operator.NotEqual).build());
+			if (detailView == null) {
+				detailView = beanSearcher.searchFirst(DistributeWaitingPointsOrderDetailView.class, MapUtils.builder().put("uid", data.getUserId()).field(DistributeWaitingPointsOrderDetailView::getStatus, DistributeWaitingSendPoints.Status.close.name()).build());
+			}
+			if (detailView != null) {
+				data.setFirstOrderId(detailView.getOrderId());
+				data.setOrderMoney(detailView.getOrderMoney());
+				data.setSpecVal(detailView.getSpecVal());
+				data.setStatus(detailView.getStatus());
+				data.setReMoney(detailView.getReMoney());
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 	}
 }
 }

+ 3 - 2
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -345,13 +345,14 @@ public class AuthorizationController {
      * 网页扫描微信公众号二维码 临时凭证ticket  关注后登录
      * 网页扫描微信公众号二维码 临时凭证ticket  关注后登录
      */
      */
     @GetMapping("/wx/gzh/login/qrCode")
     @GetMapping("/wx/gzh/login/qrCode")
-    public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId, String dsCode, String callbackType, String callback, String customId, Integer cmt) throws Exception {
+    public Result<WxGzhQrCodeTicketRep> getWxGzhQrCode(Long sharedId, Integer dsType, Long popularizeId, String dsCode, String callbackType, String callback, String customId, Integer cmt, Boolean cgTj) throws Exception {
         //获取gzh带参数的二维码
         //获取gzh带参数的二维码
         GzhBodyDto gzhBodyDto = new GzhBodyDto().setSharedId(sharedId).setDsType(dsType).setPid(popularizeId).setDsCode(dsCode)
         GzhBodyDto gzhBodyDto = new GzhBodyDto().setSharedId(sharedId).setDsType(dsType).setPid(popularizeId).setDsCode(dsCode)
                 .setCk(callback)
                 .setCk(callback)
                 .setCt(callbackType)
                 .setCt(callbackType)
                 .setCd(customId)
                 .setCd(customId)
-                .setCmt(cmt);
+                .setCmt(cmt)
+                .setCgTj(cgTj);
         WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(gzhBodyDto);
         WxGzhQrCodeTicketRep result = weChatService.getWxGzhQrCode(gzhBodyDto);
         return GatewayResponse.SUCCESS.newBuilder().toResult(result);
         return GatewayResponse.SUCCESS.newBuilder().toResult(result);
     }
     }