Bladeren bron

claude code首页优惠券折扣展示;中转服务器、积分时间倍率展示

zoujiajian 11 maanden geleden
bovenliggende
commit
c40c0e9f79

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

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

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

+ 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")
 	private Integer codeCreditRecovery;
 
+	/**
+	 * 优惠券id
+	 */
+	@DbIgnore
+	private Long couonId;
+
 	/**
 	 * 优惠价格
 	 */

+ 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.down_time is null or cr.down_time > now())
     </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>

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

@@ -6,6 +6,7 @@ import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
+import com.cyksj.model.response.TimeRateConfigsResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
@@ -66,4 +67,6 @@ public interface ClaudeCodeService {
 	 * 处理续费升级 TODO
 	 */
 	void handleClaudeCodeUserPackageSku(GroupsRelation relation, GoodsDonSku sku, Long orderId);
+
+	TimeRateConfigsResp getAllConfigs();
 }

+ 18 - 3
netflix-service/src/main/java/com/cyksj/service/claude/impl/ClaudeCodeServiceImpl.java

@@ -19,6 +19,7 @@ import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.response.ClaudeCodePointsHistoryResp;
+import com.cyksj.model.response.TimeRateConfigsResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
 import com.cyksj.model.views.ClaudeCodeUserInfoView;
@@ -68,6 +69,8 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 
 	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";
 
 	//连接超时时间 毫秒
@@ -410,6 +413,18 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		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("获取时间倍率配置列表失败");
+		}
+	}
+
 	/**
 	 * 获取claude code用户id
 	 */
@@ -435,7 +450,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 			return build.call(() -> {
 				try {
 					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)
 							.execute();
 					ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
@@ -463,7 +478,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 			return build.call(() -> {
 				try {
 					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)
 							.body(body)
 							.execute();
@@ -490,7 +505,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		try {
 			return build.call(() -> {
 				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);
 					if (!Constant.SUCCESS.equals(resp.getMessage())) {
 						log.info("claude code DELETE URL:{}接口返回msg:{}", url, resp.getMessage());

+ 83 - 33
netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java

@@ -20,6 +20,7 @@ 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.response.TimeRateConfigsResp;
 import com.cyksj.model.response.claudecode.ClaudeCodeResp;
 import com.cyksj.model.views.*;
 import com.cyksj.service.claude.AnnouncementService;
@@ -32,6 +33,7 @@ import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 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;
@@ -394,8 +396,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) {
 		//渠道推广
+		Coupon coupon = null;
 		if (dsCode != null) {
 			UserSharedDto popularizeDto = userService.getUserShredDtoByDsCode(dsCode);
 			if (popularizeDto != null) {
@@ -407,41 +424,74 @@ public class ClaudeCodeController {
 							.eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID)
 							.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.setCouonId(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);
 	}
 }