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

抽奖活动,邀请有礼活动,签到活动这几种更新

liuchengsen 1 месяц назад
Родитель
Сommit
54bf9c60c0

+ 10 - 0
zhijiayun-activity/src/main/java/com/xuekairui/activity/controller/ActivityController.java

@@ -4,6 +4,7 @@ import com.xuekairui.activity.dto.ActivityCheckinCycleStatusResponse;
 import com.xuekairui.activity.dto.ActivityInviteStatusResponse;
 import com.xuekairui.activity.dto.ActivityLotteryResultResponse;
 import com.xuekairui.activity.dto.ActivityLotteryStatusResponse;
+import com.xuekairui.activity.entity.ActivityLotteryPrize;
 import com.xuekairui.activity.entity.ActivityLotteryRecord;
 import com.xuekairui.activity.service.ActivityCheckinCycleService;
 import com.xuekairui.activity.service.ActivityInviteService;
@@ -65,6 +66,15 @@ public class ActivityController {
         return Result.success(activityLotteryService.getStatus(userId));
     }
 
+    /**
+     * 获取可抽奖品列表(用户可见,不含概率权重等敏感信息)
+     * GET /api/activity/lottery/prizes
+     */
+    @GetMapping("/lottery/prizes")
+    public Result<List<ActivityLotteryPrize>> lotteryPrizes() {
+        return Result.success(activityLotteryService.listEnabledPrizes());
+    }
+
     /**
      * 执行抽奖
      * POST /api/activity/lottery/draw

+ 3 - 0
zhijiayun-activity/src/main/java/com/xuekairui/activity/dto/ActivityCheckinCycleStatusResponse.java

@@ -42,4 +42,7 @@ public class ActivityCheckinCycleStatusResponse {
 
     /** 剩余可领取次数 */
     private Long remainingCount;
+
+    /** 达标可获会员天数 */
+    private Integer rewardDays;
 }

+ 1 - 5
zhijiayun-activity/src/main/java/com/xuekairui/activity/dto/AdminCheckInRecordResponse.java

@@ -41,13 +41,9 @@ public class AdminCheckInRecordResponse {
     /** 奖励类型 */
     private String rewardType;
 
-    /** 本次奖励数量 */
+    /** 本次奖励数量(会员天数) */
     private Integer rewardAmount;
 
-    /** 关联配额发放记录ID */
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long grantId;
-
     /** 签到端 */
     private String clientSource;
 

+ 7 - 10
zhijiayun-activity/src/main/java/com/xuekairui/activity/dto/CheckInConfigRequest.java

@@ -6,6 +6,9 @@ import lombok.Data;
 
 /**
  * 签到配置更新请求(运营端)
+ * <p>
+ * 奖励为高级会员天数:baseReward=基础天数,连续签到满 continuousThreshold 天后每天额外叠加 continuousReward 天,
+ * 叠加累计不超过 continuousCap 天。
  */
 @Data
 public class CheckInConfigRequest {
@@ -13,15 +16,12 @@ public class CheckInConfigRequest {
     @NotNull(message = "启用状态不能为空")
     private Integer enabled;
 
-    /** 奖励类型,目前固定 CRAWLER */
-    private String rewardType;
-
-    @NotNull(message = "基础奖励不能为空")
-    @Min(value = 0, message = "基础奖励不能小于0")
+    @NotNull(message = "基础会员天数不能为空")
+    @Min(value = 0, message = "基础会员天数不能小于0")
     private Integer baseReward;
 
-    @NotNull(message = "连续奖励不能为空")
-    @Min(value = 0, message = "连续奖励不能小于0")
+    @NotNull(message = "连续额外天数不能为空")
+    @Min(value = 0, message = "连续额外天数不能小于0")
     private Integer continuousReward;
 
     @NotNull(message = "连续奖励阈值不能为空")
@@ -32,8 +32,5 @@ public class CheckInConfigRequest {
     @Min(value = 1, message = "连续奖励上限至少为1")
     private Integer continuousCap;
 
-    /** 奖励有效天数(NULL=永不过期) */
-    private Integer rewardExpireDays;
-
     private String remark;
 }

+ 3 - 6
zhijiayun-activity/src/main/java/com/xuekairui/activity/entity/CheckInConfig.java

@@ -25,9 +25,9 @@ public class CheckInConfig {
     @Builder.Default
     private Integer enabled = 1;
 
-    /** 奖励类型:CRAWLER-爬虫次数 */
+    /** 奖励类型:MEMBERSHIP-会员天数 */
     @Builder.Default
-    private String rewardType = "CRAWLER";
+    private String rewardType = "MEMBERSHIP";
 
     /** 基础签到奖励(每日) */
     @Builder.Default
@@ -41,13 +41,10 @@ public class CheckInConfig {
     @Builder.Default
     private Integer continuousThreshold = 7;
 
-    /** 连续签到最大累计奖励次数上限 */
+    /** 连续签到最大累计额外天数上限 */
     @Builder.Default
     private Integer continuousCap = 30;
 
-    /** 奖励爬虫次数有效天数(NULL=永不过期) */
-    private Integer rewardExpireDays;
-
     /** 备注 */
     private String remark;
 

+ 3 - 5
zhijiayun-activity/src/main/java/com/xuekairui/activity/entity/CheckInRecord.java

@@ -33,15 +33,13 @@ public class CheckInRecord {
 
     /** 奖励类型 */
     @Builder.Default
-    private String rewardType = "CRAWLER";
 
-    /** 本次奖励数量 */
+    private String rewardType = "MEMBERSHIP";
+
+    /** 本次奖励数量(会员天数) */
     @Builder.Default
     private Integer rewardAmount = 0;
 
-    /** 关联 t_crawler_quota_grant 发放记录ID */
-    private Long grantId;
-
     /** 签到端:WINDOWS/ANDROID/MINIAPP */
     private String clientSource;
 

+ 2 - 0
zhijiayun-activity/src/main/java/com/xuekairui/activity/service/ActivityCheckinCycleService.java

@@ -187,6 +187,7 @@ public class ActivityCheckinCycleService {
 
         int currentCount = userId != null ? countCheckinInCycle(userId, currentCycleStart, currentCycleEnd) : 0;
         int requiredDays = config.getRequiredDays() != null ? config.getRequiredDays() : 4;
+        int rewardDays = config.getRewardDays() != null ? config.getRewardDays() : 7;
         long rewarded = userId != null ? cycleRecordMapper.countRewardedByUser(userId) : 0L;
         int maxReward = config.getMaxRewardCount() != null ? config.getMaxRewardCount() : 3;
         long remaining = Math.max(0, maxReward - rewarded);
@@ -202,6 +203,7 @@ public class ActivityCheckinCycleService {
                 .rewardedCount(rewarded)
                 .maxRewardCount(maxReward)
                 .remainingCount(remaining)
+                .rewardDays(rewardDays)
                 .build();
     }
 

+ 15 - 17
zhijiayun-activity/src/main/java/com/xuekairui/activity/service/ActivityLotteryService.java

@@ -16,11 +16,9 @@ import com.xuekairui.activity.mapper.ActivityLotteryPrizeMapper;
 import com.xuekairui.activity.mapper.ActivityLotteryRecordMapper;
 import com.xuekairui.common.BusinessException;
 import com.xuekairui.common.ErrorCode;
-import com.xuekairui.user.entity.CrawlerQuotaGrant;
 import com.xuekairui.user.entity.User;
 import com.xuekairui.user.enums.MembershipLevel;
 import com.xuekairui.user.mapper.UserMapper;
-import com.xuekairui.user.service.CrawlerQuotaGrantService;
 import com.xuekairui.user.service.MembershipService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -49,7 +47,6 @@ public class ActivityLotteryService {
     private static final Long CONFIG_ID = 1L;
     private static final String SOURCE_COMPARE = "COMPARE";
     private static final String REWARD_TYPE_MEMBERSHIP = "MEMBERSHIP";
-    private static final String REWARD_TYPE_CRAWLER = "CRAWLER";
     private static final String REWARD_TYPE_EMPTY = "EMPTY";
 
     private final ActivityLotteryConfigMapper configMapper;
@@ -58,7 +55,6 @@ public class ActivityLotteryService {
     private final ActivityLotteryRecordMapper recordMapper;
     private final UserMapper userMapper;
     private final MembershipService membershipService;
-    private final CrawlerQuotaGrantService crawlerQuotaGrantService;
 
     // ==========================================
     // 配置管理
@@ -266,6 +262,20 @@ public class ActivityLotteryService {
                 new LambdaQueryWrapper<ActivityLotteryPrize>().orderByAsc(ActivityLotteryPrize::getSort));
     }
 
+    /**
+     * 用户端:获取启用的奖品列表(不含概率权重)
+     */
+    public List<ActivityLotteryPrize> listEnabledPrizes() {
+        List<ActivityLotteryPrize> prizes = prizeMapper.selectList(
+                new LambdaQueryWrapper<ActivityLotteryPrize>()
+                        .eq(ActivityLotteryPrize::getEnabled, 1)
+                        .orderByAsc(ActivityLotteryPrize::getSort));
+        for (ActivityLotteryPrize p : prizes) {
+            p.setProbabilityWeight(null);
+        }
+        return prizes;
+    }
+
     @Transactional
     public ActivityLotteryPrize createPrize(ActivityLotteryPrizeRequest request) {
         ActivityLotteryPrize prize = ActivityLotteryPrize.builder()
@@ -365,7 +375,7 @@ public class ActivityLotteryService {
     }
 
     /**
-     * 根据奖品类型发放奖励
+     * 根据奖品类型发放奖励(MEMBERSHIP 或 EMPTY)
      */
     private void applyReward(Long userId, ActivityLotteryPrize prize) {
         if (REWARD_TYPE_EMPTY.equalsIgnoreCase(prize.getRewardType())) {
@@ -383,18 +393,6 @@ public class ActivityLotteryService {
             }
             membershipService.grantOrExtendMembership(userId, level, days,
                     "ACTIVITY_LOTTERY", "比价抽奖中奖:" + prize.getName());
-            return;
-        }
-        if (REWARD_TYPE_CRAWLER.equalsIgnoreCase(prize.getRewardType())) {
-            int amount = prize.getRewardAmount() != null ? prize.getRewardAmount() : 0;
-            if (amount <= 0) {
-                return;
-            }
-            LocalDateTime expireTime = LocalDateTime.now().plusDays(30);
-            CrawlerQuotaGrant grant = crawlerQuotaGrantService.grantAdminQuota(
-                    userId, amount, expireTime, "比价抽奖中奖:" + prize.getName());
-            log.info("抽奖爬虫次数奖励已发放: userId={}, amount={}, grantId={}", userId, amount,
-                    grant != null ? grant.getId() : null);
         }
     }
 }

+ 7 - 8
zhijiayun-activity/src/main/java/com/xuekairui/activity/service/CheckInConfigService.java

@@ -12,6 +12,9 @@ import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 签到配置服务(运营端)
+ * <p>
+ * 奖励体系为高级会员天数:
+ * baseReward = 每日基础会员天数,continuousReward = 连续满阈值后每日额外会员天数。
  */
 @Slf4j
 @Service
@@ -31,13 +34,12 @@ public class CheckInConfigService {
             config = CheckInConfig.builder()
                     .id(CONFIG_ID)
                     .enabled(1)
-                    .rewardType("CRAWLER")
+                    .rewardType("MEMBERSHIP")
                     .baseReward(1)
                     .continuousReward(1)
                     .continuousThreshold(7)
                     .continuousCap(30)
-                    .rewardExpireDays(30)
-                    .remark("默认签到配置")
+                    .remark("默认签到配置:每日1天高级会员,连续7天起每日额外+1天")
                     .build();
             checkinConfigMapper.insert(config);
         }
@@ -51,17 +53,14 @@ public class CheckInConfigService {
     public CheckInConfig updateConfig(CheckInConfigRequest request) {
         CheckInConfig config = getConfig();
         config.setEnabled(request.getEnabled());
-        if (request.getRewardType() != null && !request.getRewardType().isBlank()) {
-            config.setRewardType(request.getRewardType());
-        }
+        config.setRewardType("MEMBERSHIP");
         config.setBaseReward(request.getBaseReward());
         config.setContinuousReward(request.getContinuousReward());
         config.setContinuousThreshold(request.getContinuousThreshold());
         config.setContinuousCap(request.getContinuousCap());
-        config.setRewardExpireDays(request.getRewardExpireDays());
         config.setRemark(request.getRemark());
         checkinConfigMapper.updateById(config);
-        log.info("签到配置已更新: enabled={}, baseReward={}, continuousReward={}, threshold={}",
+        log.info("签到配置已更新: enabled={}, baseReward={}, continuousReward={}, threshold={}",
                 config.getEnabled(), config.getBaseReward(),
                 config.getContinuousReward(), config.getContinuousThreshold());
         return config;

+ 11 - 29
zhijiayun-activity/src/main/java/com/xuekairui/activity/service/CheckInService.java

@@ -13,15 +13,14 @@ import com.xuekairui.activity.entity.CheckInRecord;
 import com.xuekairui.activity.mapper.CheckInRecordMapper;
 import com.xuekairui.common.BusinessException;
 import com.xuekairui.common.ErrorCode;
-import com.xuekairui.user.entity.CrawlerQuotaGrant;
-import com.xuekairui.user.service.CrawlerQuotaGrantService;
+import com.xuekairui.user.enums.MembershipLevel;
+import com.xuekairui.user.service.MembershipService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -32,20 +31,17 @@ import java.util.stream.Collectors;
  * 业务规则:
  * 1. 每个用户每个自然日仅可签到一次(DB 唯一索引兜底)
  * 2. 连续签到:若昨日已签到,则连续天数 +1;否则重置为 1
- * 3. 奖励计算:基础奖励 + (连续天数 >= 阈值 ? 连续奖励 : 0),且累计连续奖励不超过 continuousCap
- * 4. 奖励以爬虫次数发放,复用 t_crawler_quota_grant(grant_type=CHECKIN)
+ * 3. 奖励计算:基础会员天数 + (连续天数 >= 阈值 ? 额外会员天数 : 0),累计额外不超过 continuousCap
+ * 4. 奖励以高级会员天数发放,通过 MembershipService 续期
  */
 @Slf4j
 @Service
 @RequiredArgsConstructor
 public class CheckInService {
 
-    /** 签到发放爬虫配额类型 */
-    public static final String GRANT_TYPE_CHECKIN = "CHECKIN";
-
     private final CheckInConfigService checkinConfigService;
     private final CheckInRecordMapper checkinRecordMapper;
-    private final CrawlerQuotaGrantService crawlerQuotaGrantService;
+    private final MembershipService membershipService;
     private final ActivityCheckinCycleService activityCheckinCycleService;
 
     /**
@@ -78,7 +74,7 @@ public class CheckInService {
     }
 
     /**
-     * 执行签到
+     * 执行签到,发放高级会员天数
      */
     @Transactional
     public CheckInResultResponse doCheckIn(Long userId, String clientSource) {
@@ -94,13 +90,8 @@ public class CheckInService {
         int continuousDays = calcContinuousDays(userId, today) + 1;
         int rewardAmount = calcReward(config, continuousDays);
 
-        LocalDateTime expireTime = config.getRewardExpireDays() != null
-                ? LocalDateTime.now().plusDays(config.getRewardExpireDays())
-                : null;
-
-        CrawlerQuotaGrant grant = crawlerQuotaGrantService.grantAdminQuota(
-                userId, rewardAmount, expireTime,
-                "签到奖励 连续第" + continuousDays + "天");
+        membershipService.grantOrExtendMembership(userId, MembershipLevel.PRO, rewardAmount,
+                "CHECKIN", "签到奖励 连续第" + continuousDays + "天 获" + rewardAmount + "天高级会员");
 
         CheckInRecord record = CheckInRecord.builder()
                 .userId(userId)
@@ -108,15 +99,13 @@ public class CheckInService {
                 .continuousDays(continuousDays)
                 .rewardType(config.getRewardType())
                 .rewardAmount(rewardAmount)
-                .grantId(grant != null ? grant.getId() : null)
                 .clientSource(clientSource)
                 .build();
         checkinRecordMapper.insert(record);
 
-        log.info("用户签到成功: userId={}, date={}, continuous={}, reward={}",
+        log.info("用户签到成功: userId={}, date={}, continuous={}, reward={}天高级会员",
                 userId, today, continuousDays, rewardAmount);
 
-        // 签到送会员活动:尝试发放上一周期奖励(活动关闭时内部直接返回,不影响原逻辑)
         try {
             activityCheckinCycleService.tryGrantCycleReward(userId);
         } catch (Exception e) {
@@ -179,12 +168,6 @@ public class CheckInService {
 
     /**
      * 运营端:分页查询签到记录(关联用户信息)
-     *
-     * @param page         分页对象
-     * @param userId       用户ID(可选)
-     * @param startDate    起始日期(可选)
-     * @param endDate      截止日期(可选)
-     * @param clientSource 签到端(可选)
      */
     public IPage<AdminCheckInRecordResponse> adminListRecords(Page<AdminCheckInRecordResponse> page,
                                                               Long userId,
@@ -215,7 +198,7 @@ public class CheckInService {
     }
 
     /**
-     * 运营端:查询指定用户的签到记录(含用户基础信息,最多500条)
+     * 运营端:查询指定用户的签到记录
      */
     public List<AdminCheckInRecordResponse> adminListUserRecords(Long userId) {
         if (userId == null) {
@@ -242,7 +225,6 @@ public class CheckInService {
 
     /**
      * 计算截至 today 的连续签到天数(不含 today)
-     * 若昨天签到则为昨天连续天数+1,否则为 0
      */
     private int calcContinuousDays(Long userId, LocalDate today) {
         CheckInRecord yesterday = findRecord(userId, today.minusDays(1));
@@ -253,7 +235,7 @@ public class CheckInService {
     }
 
     /**
-     * 计算签到奖励:基础 + 连续奖励(达阈值后叠加,受上限约束)
+     * 计算签到奖励(会员天数):基础天数 + 连续额外天数(达阈值后叠加,受上限约束)
      */
     private int calcReward(CheckInConfig config, int continuousDays) {
         int reward = config.getBaseReward();

+ 0 - 1
zhijiayun-activity/src/main/resources/mapper/CheckInRecordMapper.xml

@@ -15,7 +15,6 @@
             r.continuous_days AS continuousDays,
             r.reward_type     AS rewardType,
             r.reward_amount   AS rewardAmount,
-            r.grant_id        AS grantId,
             r.client_source   AS clientSource,
             r.create_time     AS createTime
         FROM t_checkin_record r

+ 10 - 12
zhijiayun-gateway/src/main/resources/db/migration-v10.sql

@@ -1,18 +1,17 @@
 -- ============================================
 -- 迁移 v10:签到有礼(活动模块)
--- 说明:签到奖励以爬虫次数形式发放,复用 t_crawler_quota_grant 表(grant_type=CHECKIN)
+-- 说明:签到奖励以高级会员天数形式发放,通过 MembershipService 续期
 -- ============================================
 
 -- 1. 签到配置表(全局唯一一条记录,运营后台可编辑)
 CREATE TABLE IF NOT EXISTS `t_checkin_config` (
     `id`                   BIGINT        NOT NULL AUTO_INCREMENT COMMENT '主键ID',
     `enabled`              TINYINT       NOT NULL DEFAULT 1 COMMENT '是否启用签到:0-停用 1-启用',
-    `reward_type`          VARCHAR(20)   NOT NULL DEFAULT 'CRAWLER' COMMENT '奖励类型:CRAWLER-爬虫次数(预留 POINTS/COUPON)',
-    `base_reward`          INT           NOT NULL DEFAULT 1 COMMENT '基础签到奖励(每日)',
-    `continuous_reward`    INT           NOT NULL DEFAULT 1 COMMENT '连续签到额外奖励(满足连续天数后每日叠加)',
-    `continuous_threshold` INT           NOT NULL DEFAULT 7 COMMENT '连续签到奖励触发阈值(天)',
-    `continuous_cap`       INT           NOT NULL DEFAULT 30 COMMENT '连续签到最大累计奖励次数上限',
-    `reward_expire_days`   INT           DEFAULT NULL COMMENT '奖励爬虫次数有效天数(NULL=永不过期)',
+    `reward_type`          VARCHAR(20)   NOT NULL DEFAULT 'MEMBERSHIP' COMMENT '奖励类型:MEMBERSHIP-会员天数',
+    `base_reward`          INT           NOT NULL DEFAULT 1 COMMENT '基础签到奖励会员天数(每日)',
+    `continuous_reward`    INT           NOT NULL DEFAULT 1 COMMENT '连续签到额外会员天数(满足连续天数后每日叠加)',
+    `continuous_threshold` INT           NOT NULL DEFAULT 7 COMMENT '连续签到额外奖励触发阈值(天)',
+    `continuous_cap`       INT           NOT NULL DEFAULT 30 COMMENT '连续签到最大累计额外天数上限',
     `remark`               VARCHAR(500)  DEFAULT NULL COMMENT '备注说明',
     `create_time`          DATETIME      DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     `update_time`          DATETIME      DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
@@ -21,8 +20,8 @@ CREATE TABLE IF NOT EXISTS `t_checkin_config` (
 
 -- 初始化默认配置(id=1)
 INSERT INTO `t_checkin_config` (`id`, `enabled`, `reward_type`, `base_reward`, `continuous_reward`,
-                                `continuous_threshold`, `continuous_cap`, `reward_expire_days`, `remark`)
-VALUES (1, 1, 'CRAWLER', 1, 1, 7, 30, 30, '默认签到配置:每日1次,连续7天起每日额外+1,单次奖励30天有效')
+                                `continuous_threshold`, `continuous_cap`, `remark`)
+VALUES (1, 1, 'MEMBERSHIP', 1, 1, 7, 30, '默认签到配置:每日1天高级会员,连续7天起每日额外+1天')
 ON DUPLICATE KEY UPDATE id = id;
 
 -- 2. 用户签到记录表(每日一条,唯一索引保证一人一天一次)
@@ -31,9 +30,8 @@ CREATE TABLE IF NOT EXISTS `t_checkin_record` (
     `user_id`          BIGINT        NOT NULL COMMENT '用户ID',
     `checkin_date`     DATE          NOT NULL COMMENT '签到日期(自然日)',
     `continuous_days`  INT           NOT NULL DEFAULT 1 COMMENT '签到时连续天数',
-    `reward_type`      VARCHAR(20)   NOT NULL DEFAULT 'CRAWLER' COMMENT '奖励类型',
-    `reward_amount`    INT           NOT NULL DEFAULT 0 COMMENT '本次奖励数量',
-    `grant_id`         BIGINT        DEFAULT NULL COMMENT '关联 t_crawler_quota_grant 发放记录ID',
+    `reward_type`      VARCHAR(20)   NOT NULL DEFAULT 'MEMBERSHIP' COMMENT '奖励类型',
+    `reward_amount`    INT           NOT NULL DEFAULT 0 COMMENT '本次奖励会员天数',
     `client_source`   VARCHAR(20)   DEFAULT NULL COMMENT '签到端:WINDOWS/ANDROID/MINIAPP',
     `create_time`      DATETIME      DEFAULT CURRENT_TIMESTAMP COMMENT '签到时间',
     PRIMARY KEY (`id`),

+ 3 - 4
zhijiayun-gateway/src/main/resources/db/migration-v11.sql

@@ -119,7 +119,7 @@ CREATE TABLE IF NOT EXISTS `t_activity_lottery_chance` (
 CREATE TABLE IF NOT EXISTS `t_activity_lottery_prize` (
     `id`                 BIGINT       NOT NULL AUTO_INCREMENT,
     `name`               VARCHAR(50)  NOT NULL COMMENT '奖品名称',
-    `reward_type`        VARCHAR(20)  NOT NULL COMMENT '奖励类型:MEMBERSHIP-会员 CRAWLER-爬虫次数 EMPTY-未中奖',
+    `reward_type`        VARCHAR(20)  NOT NULL COMMENT '奖励类型:MEMBERSHIP-会员 EMPTY-未中奖',
     `reward_amount`      INT          NOT NULL DEFAULT 0 COMMENT '奖励数量(爬虫次数等)',
     `reward_days`        INT          DEFAULT NULL COMMENT '奖励会员天数(MEMBERSHIP类型)',
     `reward_level`       VARCHAR(20)  DEFAULT NULL COMMENT '奖励会员等级(MEMBERSHIP类型)',
@@ -136,9 +136,8 @@ INSERT INTO `t_activity_lottery_prize` (`name`, `reward_type`, `reward_amount`,
 VALUES
 ('高级会员7天', 'MEMBERSHIP', 0, 7, 'PRO', 10, 1, 1),
 ('高级会员3天', 'MEMBERSHIP', 0, 3, 'PRO', 20, 1, 2),
-('爬虫次数5次', 'CRAWLER', 5, NULL, NULL, 30, 1, 3),
-('爬虫次数2次', 'CRAWLER', 2, NULL, NULL, 40, 1, 4),
-('谢谢参与', 'EMPTY', 0, NULL, NULL, 100, 1, 5);
+('高级会员1天', 'MEMBERSHIP', 0, 1, 'PRO', 40, 1, 3),
+('谢谢参与', 'EMPTY', 0, NULL, NULL, 100, 1, 4);
 
 -- 抽奖记录表
 CREATE TABLE IF NOT EXISTS `t_activity_lottery_record` (

+ 173 - 43
zhijiayun-test/src/main/resources/static/activity-test.html

@@ -73,6 +73,11 @@
         .field-desc-table td { padding: 4px 8px; border: 1px solid #ddd; color: #555; }
         .field-desc-table td code { background: #e8e8e8; padding: 1px 4px; border-radius: 2px; font-size: 11px; }
 
+        .field-desc-details { margin-bottom: 12px; background: #f5f7fa; border: 1px solid #e0e0e0; border-radius: 4px; padding: 8px 12px; }
+        .field-desc-summary { cursor: pointer; font-size: 13px; font-weight: 600; color: #555; user-select: none; padding: 2px 0; }
+        .field-desc-summary:hover { color: #1976d2; }
+        .curl-example { background: #1e1e1e; color: #dcdcaa; padding: 12px 14px; border-radius: 4px; font-family: Consolas, Monaco, 'Courier New', monospace; font-size: 12px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 6px 0 0 0; line-height: 1.6; }
+
         .summary-bar { display: flex; gap: 16px; padding: 12px 16px; background: white; border-radius: 8px; margin-bottom: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); align-items: center; flex-wrap: wrap; }
         .summary-item { display: flex; align-items: center; gap: 6px; font-size: 14px; }
         .summary-count { font-weight: 700; font-size: 20px; }
@@ -460,7 +465,7 @@ const FIELD_DESC = {
     'checkinStatus': [
         ['data.checkedToday', 'Boolean', '今日是否已签到'],
         ['data.continuousDays', 'Integer', '当前连续签到天数(今日未签到时为若签到将达成的天数-1)'],
-        ['data.todayReward', 'Integer', '今日签到可获奖励数量'],
+        ['data.todayReward', 'Integer', '今日签到可获会员天数'],
         ['data.nextCheckinDate', 'Date', '下一次可签到日期(今日未签到=今天)'],
         ['data.enabled', 'Boolean', '签到功能是否启用']
     ],
@@ -468,8 +473,8 @@ const FIELD_DESC = {
         ['data.id', 'Long', '签到记录ID'],
         ['data.checkinDate', 'Date', '签到日期'],
         ['data.continuousDays', 'Integer', '签到时连续天数'],
-        ['data.rewardAmount', 'Integer', '本次奖励数量(爬虫次数)'],
-        ['data.rewardType', 'String', '奖励类型(CRAWLER)'],
+        ['data.rewardAmount', 'Integer', '本次奖励会员天数'],
+        ['data.rewardType', 'String', '奖励类型(MEMBERSHIP)'],
         ['data.createTime', 'DateTime', '签到时间']
     ],
     'checkinCalendar': [
@@ -482,12 +487,11 @@ const FIELD_DESC = {
     'checkinConfig': [
         ['data.id', 'Long', '配置ID(固定1)'],
         ['data.enabled', 'Integer', '是否启用:0-停用 1-启用'],
-        ['data.rewardType', 'String', '奖励类型(CRAWLER)'],
-        ['data.baseReward', 'Integer', '基础签到奖励(每日)'],
-        ['data.continuousReward', 'Integer', '连续签到额外奖励'],
-        ['data.continuousThreshold', 'Integer', '连续奖励触发阈值(天)'],
-        ['data.continuousCap', 'Integer', '连续奖励累计上限'],
-        ['data.rewardExpireDays', 'Integer', '奖励有效天数(null=永久)'],
+        ['data.rewardType', 'String', '奖励类型(MEMBERSHIP-会员天数)'],
+        ['data.baseReward', 'Integer', '基础会员天数(每日)'],
+        ['data.continuousReward', 'Integer', '连续签到额外会员天数'],
+        ['data.continuousThreshold', 'Integer', '连续额外触发阈值(天)'],
+        ['data.continuousCap', 'Integer', '连续额外累计上限(天)'],
         ['data.remark', 'String', '备注'],
         ['data.createTime', 'DateTime', '创建时间'],
         ['data.updateTime', 'DateTime', '更新时间']
@@ -499,7 +503,7 @@ const FIELD_DESC = {
         ['data.last30DaysCount', 'Long', '近30天签到人数(去重)'],
         ['data.totalCheckinCount', 'Long', '累计签到总次数'],
         ['data.totalCheckinUsers', 'Long', '累计签到用户数(去重)'],
-        ['data.totalRewardAmount', 'Long', '累计发放奖励次数总和'],
+        ['data.totalRewardAmount', 'Long', '累计发放会员天数总和'],
         ['data.statDate', 'Date', '统计日期'],
         ['data.enabled', 'Boolean', '签到功能是否启用']
     ],
@@ -512,14 +516,113 @@ const FIELD_DESC = {
         ['data.records[].checkinDate', 'Date', '签到日期'],
         ['data.records[].continuousDays', 'Integer', '签到时连续天数'],
         ['data.records[].rewardType', 'String', '奖励类型'],
-        ['data.records[].rewardAmount', 'Integer', '本次奖励数量'],
-        ['data.records[].grantId', 'Long', '关联配额发放记录ID'],
+        ['data.records[].rewardAmount', 'Integer', '本次奖励会员天数'],
         ['data.records[].clientSource', 'String', '签到端'],
         ['data.records[].createTime', 'DateTime', '签到时间'],
         ['data.total', 'Long', '总记录数'],
         ['data.current', 'Long', '当前页'],
         ['data.size', 'Long', '每页条数'],
         ['data.pages', 'Long', '总页数']
+    ],
+    'activityInviteStatus': [
+        ['data.enabled', 'Boolean', '活动是否启用'],
+        ['data.inWindow', 'Boolean', '是否在活动时间窗内'],
+        ['data.rewardedCount', 'Long', '已获奖励次数'],
+        ['data.maxInviterReward', 'Integer', '邀请人最多奖励次数'],
+        ['data.remainingCount', 'Long', '剩余可获奖励次数']
+    ],
+    'activityCheckinStatus': [
+        ['data.enabled', 'Boolean', '活动是否启用'],
+        ['data.inWindow', 'Boolean', '是否在活动时间窗内'],
+        ['data.currentCycleStart', 'Date', '当前周期起始日(周五)'],
+        ['data.currentCycleEnd', 'Date', '当前周期截止日(下周四)'],
+        ['data.currentCycleCheckinCount', 'Integer', '当前周期内已签到天数'],
+        ['data.requiredDays', 'Integer', '达标所需签到天数'],
+        ['data.reachedTarget', 'Boolean', '当前周期是否已达标'],
+        ['data.rewardDays', 'Integer', '达标后可获会员天数'],
+        ['data.rewardedCount', 'Long', '已领取奖励次数'],
+        ['data.maxRewardCount', 'Integer', '最多可领取奖励次数'],
+        ['data.remainingCount', 'Long', '剩余可领取奖励次数']
+    ],
+    'activityLotteryStatus': [
+        ['data.enabled', 'Boolean', '活动是否启用'],
+        ['data.inWindow', 'Boolean', '是否在活动时间窗内'],
+        ['data.eligible', 'Boolean', '是否满足参与资格(会员等级)'],
+        ['data.membershipLevel', 'String', '当前用户会员等级'],
+        ['data.requireMembershipLevel', 'String', '所需会员等级'],
+        ['data.availableChances', 'Integer', '今日可用抽奖机会数'],
+        ['data.usedChances', 'Integer', '今日已用抽奖机会数']
+    ],
+    'activityLotteryPrizes': [
+        ['data[].id', 'Long', '奖品ID'],
+        ['data[].name', 'String', '奖品名称'],
+        ['data[].rewardType', 'String', '奖励类型(MEMBERSHIP会员/CRAWLER爬虫次数/EMPTY谢谢参与)'],
+        ['data[].rewardDays', 'Integer', '会员奖励天数'],
+        ['data[].rewardLevel', 'String', '会员奖励等级(PRO/ULTRA)'],
+        ['data[].rewardAmount', 'Integer', '爬虫奖励次数(CRAWLER类型时有效,暂未实现)'],
+        ['data[].sort', 'Integer', '排序']
+    ],
+    'activityLotteryDraw': [
+        ['data.recordId', 'Long', '抽奖记录ID'],
+        ['data.prizeName', 'String', '奖品名称'],
+        ['data.rewardType', 'String', '奖励类型(MEMBERSHIP会员/CRAWLER爬虫次数/EMPTY谢谢参与)'],
+        ['data.rewardAmount', 'Integer', '奖励数量(预留)'],
+        ['data.rewardDays', 'Integer', '会员奖励天数'],
+        ['data.rewardLevel', 'String', '会员奖励等级(PRO/ULTRA)'],
+        ['data.win', 'Boolean', '是否中奖(EMPTY=未中奖)'],
+        ['data.createTime', 'DateTime', '抽奖时间']
+    ],
+    'adminActivityInviteConfig': [
+        ['data.id', 'Long', '配置ID(固定1)'],
+        ['data.enabled', 'Integer', '是否启用:0-停用 1-启用'],
+        ['data.startTime', 'DateTime', '活动开始时间'],
+        ['data.endTime', 'DateTime', '活动结束时间'],
+        ['data.inviterRewardDays', 'Integer', '邀请人奖励天数'],
+        ['data.inviteeRewardDays', 'Integer', '被邀请人奖励天数'],
+        ['data.maxInviterReward', 'Integer', '邀请人最多奖励次数'],
+        ['data.rewardTrigger', 'String', '奖励触发模式(REGISTRATION/LICENSE_APPROVED)'],
+        ['data.requireMiniappInviter', 'Integer', '是否要求邀请人为小程序用户:0-否 1-是'],
+        ['data.remark', 'String', '备注'],
+        ['data.createTime', 'DateTime', '创建时间'],
+        ['data.updateTime', 'DateTime', '更新时间']
+    ],
+    'adminActivityInviteRevoke': [
+        ['data', 'Integer', '撤销的奖励记录数']
+    ],
+    'adminActivityCheckinConfig': [
+        ['data.id', 'Long', '配置ID(固定1)'],
+        ['data.enabled', 'Integer', '是否启用:0-停用 1-启用'],
+        ['data.startTime', 'DateTime', '活动开始时间'],
+        ['data.endTime', 'DateTime', '活动结束时间'],
+        ['data.cycleMode', 'String', '周期模式(FRI_THU=周五至下周四)'],
+        ['data.requiredDays', 'Integer', '达标所需签到天数'],
+        ['data.rewardDays', 'Integer', '达标奖励会员天数'],
+        ['data.maxRewardCount', 'Integer', '每人最多可领取奖励次数'],
+        ['data.remark', 'String', '备注'],
+        ['data.createTime', 'DateTime', '创建时间'],
+        ['data.updateTime', 'DateTime', '更新时间']
+    ],
+    'adminActivityLotteryConfig': [
+        ['data.id', 'Long', '配置ID(固定1)'],
+        ['data.enabled', 'Integer', '是否启用:0-停用 1-启用'],
+        ['data.startTime', 'DateTime', '活动开始时间'],
+        ['data.endTime', 'DateTime', '活动结束时间'],
+        ['data.dailyMaxChance', 'Integer', '每个自然日最多获得抽奖机会数'],
+        ['data.requireMembershipLevel', 'String', '参与所需会员等级(PRO/ULTRA/PLUS)'],
+        ['data.remark', 'String', '备注'],
+        ['data.createTime', 'DateTime', '创建时间'],
+        ['data.updateTime', 'DateTime', '更新时间']
+    ],
+    'adminActivityLotteryPrize': [
+        ['data.id', 'Long', '奖品ID'],
+        ['data.name', 'String', '奖品名称'],
+        ['data.rewardType', 'String', '奖励类型(MEMBERSHIP会员/CRAWLER爬虫次数/EMPTY谢谢参与)'],
+        ['data.rewardAmount', 'Integer', '奖励数量(预留)'],
+        ['data.rewardDays', 'Integer', '会员奖励天数'],
+        ['data.rewardLevel', 'String', '会员奖励等级'],
+        ['data.probabilityWeight', 'Integer', '中奖概率权重(越大越容易中)'],
+        ['data.enabled', 'Integer', '是否启用:0-停用 1-启用'],
+        ['data.sort', 'Integer', '排序(数字越小越靠前)']
     ]
 };
 
@@ -527,10 +630,35 @@ function renderFieldDesc(descKey) {
     const fields = FIELD_DESC[descKey];
     if (!fields) return '';
     let rows = fields.map(f => `<tr><td><code>${f[0]}</code></td><td>${f[1]}</td><td>${f[2]}</td></tr>`).join('');
-    return `<div class="field-desc-box">
-        <div class="field-desc-title">返回字段说明</div>
+    return `<details open class="field-desc-details">
+        <summary class="field-desc-summary">📋 返回字段说明</summary>
         <table class="field-desc-table"><tr><th>字段名</th><th>类型</th><th>说明</th></tr>${rows}</table>
-    </div>`;
+    </details>`;
+}
+
+// ==================== 调用示例生成 ====================
+function renderCurlExample(id, method, path, fields) {
+    const methodUpper = method.toUpperCase();
+    const baseUrl = document.getElementById('baseUrl').value;
+    let curl = `curl -X ${methodUpper} "${baseUrl}${path}"`;
+    curl += ` \\\n  -H "Authorization: Bearer \${TOKEN}"`;
+    if (methodUpper === 'POST' || methodUpper === 'PUT') {
+        curl += ` \\\n  -H "Content-Type: application/json"`;
+    }
+    if (fields && fields.length > 0) {
+        let bodyParts = [];
+        fields.forEach(f => {
+            let val = f.default || f.placeholder || '';
+            bodyParts.push(`"${f.name}": "${val}"`);
+        });
+        if (bodyParts.length > 0) {
+            curl += ` \\\n  -d '{${bodyParts.join(', ')}}'`;
+        }
+    }
+    return `<details class="field-desc-details">
+        <summary class="field-desc-summary">📞 cURL 调用示例</summary>
+        <pre class="curl-example">${curl}</pre>
+    </details>`;
 }
 
 // ==================== 测试用例区块渲染 ====================
@@ -553,6 +681,7 @@ function testSection(id, title, method, methodClass, path, authTag, authClass, f
     }
     const descHtml = desc ? `<div class="section-desc">${desc}</div>` : '';
     const fieldDescHtml = descKey ? renderFieldDesc(descKey) : '';
+    const curlHtml = renderCurlExample(id, method, path, fields);
     return `
     <div class="test-section">
         <div class="section-title">
@@ -562,6 +691,8 @@ function testSection(id, title, method, methodClass, path, authTag, authClass, f
             <span class="${ac} auth-tag">${authLabel}</span>
         </div>
         ${descHtml}
+        ${curlHtml}
+        ${fieldDescHtml}
         ${fieldsHtml}
         <button class="btn btn-primary" onclick="runTest('${id}', '${method}', '${path}', ${buildBody(id, fields)}, ${authTag === '公开' ? 'false' : 'true'}, ${hasValidator ? `'${toValidatorName(id)}'` : 'null'})">执行测试</button>
         <div class="response-box" id="${id}-box" style="display:none;">
@@ -570,7 +701,6 @@ function testSection(id, title, method, methodClass, path, authTag, authClass, f
                 <span class="status-badge" id="${id}-status"></span>
             </div>
             <div class="response-content" id="${id}-raw"></div>
-            ${fieldDescHtml}
         </div>
     </div>`;
 }
@@ -618,9 +748,9 @@ function renderCheckinModule() {
     <div class="batch-buttons">
         <button class="btn btn-warning btn-sm" onclick="runCheckinTests()">运行全部签到测试</button>
     </div>
-    ${testSection('checkin-status', '今日签到状态', 'GET', 'get', '/api/checkin/status', '需认证', 'auth-required', null, true, 'checkinStatus', '获取当前用户今日签到状态、连续天数、可获奖励')}
+    ${testSection('checkin-status', '今日签到状态', 'GET', 'get', '/api/checkin/status', '需认证', 'auth-required', null, true, 'checkinStatus', '获取当前用户今日签到状态、连续天数、可获会员天数')}
     ${testSection('checkin-do', '执行签到', 'POST', 'post', '/api/checkin', '需认证', 'auth-required',
-        [{label:'签到端(clientSource,可选)', name:'clientSource', placeholder:'WINDOWS/ANDROID/MINIAPP', default:'WINDOWS'}], true, 'checkinResult', '执行当日签到,发放爬虫次数奖励。每个自然日仅可签到一次')}
+        [{label:'签到端(clientSource,可选)', name:'clientSource', placeholder:'WINDOWS/ANDROID/MINIAPP', default:'WINDOWS'}], true, 'checkinResult', '执行当日签到,发放高级会员天数奖励。每个自然日仅可签到一次')}
     ${testSection('checkin-calendar', '当月签到日历', 'GET', 'get', '/api/checkin/calendar?year=2026&month=7', '需认证', 'auth-required',
         [{label:'年份(year,可选)', name:'year', placeholder:'2026', default:'2026'},
          {label:'月份(month,可选)', name:'month', placeholder:'7', default:'7'}], true, 'checkinCalendar', '获取指定月份的签到日历,不传默认当月')}
@@ -652,6 +782,7 @@ function renderActivityLotteryModule() {
     <div class="batch-buttons">
         <button class="btn btn-warning btn-sm" onclick="runActivityLotteryTests()">运行全部比价抽奖测试</button>
     </div>
+    ${testSection('activity-lottery-prizes', '奖励信息(可抽奖品列表)', 'GET', 'get', '/api/activity/lottery/prizes', '需认证', 'auth-required', null, true, 'activityLotteryPrizes', '查看当前可抽奖品列表(仅启用奖品,不显示概率权重等敏感信息)')}
     ${testSection('activity-lottery-status', '比价抽奖活动状态', 'GET', 'get', '/api/activity/lottery/status', '需认证', 'auth-required', null, true, 'activityLotteryStatus', '查询抽奖活动状态:是否开启、是否满足资格、今日可用机会')}
     ${testSection('activity-lottery-draw', '执行抽奖', 'POST', 'post', '/api/activity/lottery/draw', '需认证', 'auth-required', null, true, 'activityLotteryDraw', '消耗一次抽奖机会,随机抽取奖品(会员/爬虫次数/谢谢参与)')}
     ${testSection('activity-lottery-records', '我的抽奖记录', 'GET', 'get', '/api/activity/lottery/records?limit=20', '需认证', 'auth-required',
@@ -668,14 +799,12 @@ function renderAdminCheckinModule() {
     ${testSection('admin-checkin-config-update', '更新签到配置', 'PUT', 'put', '/api/admin/checkin/config', '需认证', 'auth-required',
         [
          {label:'启用(enabled)', name:'enabled', placeholder:'0停用/1启用', default:'1'},
-         {label:'奖励类型(rewardType)', name:'rewardType', placeholder:'CRAWLER', default:'CRAWLER'},
-         {label:'基础奖励(baseReward)', name:'baseReward', placeholder:'1', default:'1'},
-         {label:'连续奖励(continuousReward)', name:'continuousReward', placeholder:'1', default:'1'},
+         {label:'基础会员天数(baseReward)', name:'baseReward', placeholder:'1', default:'1'},
+         {label:'连续额外天数(continuousReward)', name:'continuousReward', placeholder:'1', default:'1'},
          {label:'连续阈值(continuousThreshold)', name:'continuousThreshold', placeholder:'7', default:'7'},
-         {label:'连续上限(continuousCap)', name:'continuousCap', placeholder:'30', default:'30'},
-         {label:'有效天数(rewardExpireDays)', name:'rewardExpireDays', placeholder:'30', default:'30'},
-         {label:'备注(remark)', name:'remark', placeholder:'默认签到配置', default:'默认签到配置:每日1次,连续7天起每日额外+1'}
-        ], true, 'checkinConfig', '更新签到规则配置。连续签到满阈值后每日额外发放continuousReward,累计不超过continuousCap')}
+         {label:'连续额外上限(continuousCap)', name:'continuousCap', placeholder:'30', default:'30'},
+         {label:'备注(remark)', name:'remark', placeholder:'默认签到配置', default:'默认签到配置:每日1天高级会员,连续7天起每日额外+1天'}
+        ], true, 'checkinConfig', '更新签到规则配置。连续签到满阈值后每日额外发放 continuousReward 天,累计不超过 continuousCap 天')}
     ${testSection('admin-checkin-stats', '签到统计概览', 'GET', 'get', '/api/admin/checkin/stats', '需认证', 'auth-required', null, true, 'checkinStats', '签到数据统计:今日/昨日/近7天/近30天签到人数、累计签到次数与用户数、累计发放奖励')}
     ${testSection('admin-checkin-records', '签到记录分页查询', 'GET', 'get', '/api/admin/checkin/records?page=1&size=10&userId=1&startDate=2026-07-01&endDate=2026-07-07&clientSource=WINDOWS', '需认证', 'auth-required',
         [{label:'页码(page)', name:'page', placeholder:'1', default:'1'},
@@ -753,26 +882,26 @@ function renderAdminActivityLotteryModule() {
     ${testSection('admin-activity-lottery-prizes', '奖品池列表', 'GET', 'get', '/api/admin/activity/lottery/prizes', '需认证', 'auth-required', null, true, null, '获取所有奖品及其权重配置')}
     ${testSection('admin-activity-lottery-prize-create', '新增奖品', 'POST', 'post', '/api/admin/activity/lottery/prizes', '需认证', 'auth-required',
         [
-         {label:'奖品名称(name)', name:'name', placeholder:'高级会员3天', default:'爬虫次数+10'},
-         {label:'奖励类型(rewardType)', name:'rewardType', placeholder:'MEMBERSHIP/CRAWLER/EMPTY', default:'CRAWLER'},
-         {label:'奖励数量(rewardAmount)', name:'rewardAmount', placeholder:'爬虫次数填数量', default:'10'},
-         {label:'会员天数(rewardDays)', name:'rewardDays', placeholder:'MEMBERSHIP类型填', default:''},
-         {label:'会员等级(rewardLevel)', name:'rewardLevel', placeholder:'PRO/ULTRA', default:''},
-         {label:'概率权重(probabilityWeight)', name:'probabilityWeight', placeholder:'权重越大越容易中', default:'5'},
+         {label:'奖品名称(name)', name:'name', placeholder:'高级会员3天', default:'高级会员3天'},
+         {label:'奖励类型(rewardType)', name:'rewardType', placeholder:'MEMBERSHIP/CRAWLER/EMPTY', default:'MEMBERSHIP'},
+         {label:'会员天数(rewardDays)', name:'rewardDays', placeholder:'3', default:'3'},
+         {label:'会员等级(rewardLevel)', name:'rewardLevel', placeholder:'PRO/ULTRA', default:'PRO'},
+         {label:'爬虫次数(rewardAmount)', name:'rewardAmount', placeholder:'CRAWLER类型时填写', default:'0'},
+         {label:'概率权重(probabilityWeight)', name:'probabilityWeight', placeholder:'权重越大越容易中', default:'20'},
          {label:'启用(enabled)', name:'enabled', placeholder:'0停用/1启用', default:'1'},
-         {label:'排序(sort)', name:'sort', placeholder:'0', default:'6'}
-        ], true, 'adminActivityLotteryPrize', '新增奖品到奖品池。rewardType: MEMBERSHIP会员/CRAWLER爬虫/EMPTY谢谢参与')}
+         {label:'排序(sort)', name:'sort', placeholder:'0', default:'3'}
+        ], true, 'adminActivityLotteryPrize', '新增奖品到奖品池。rewardType: MEMBERSHIP会员/CRAWLER爬虫次数(暂未实现)/EMPTY谢谢参与')}
     ${testSection('admin-activity-lottery-prize-update', '更新奖品', 'PUT', 'put', '/api/admin/activity/lottery/prizes/{id}', '需认证', 'auth-required',
         [
          {label:'奖品ID(id)', name:'id', placeholder:'1', default:''},
-         {label:'奖品名称(name)', name:'name', placeholder:'高级会员3天', default:'爬虫次数+10'},
-         {label:'奖励类型(rewardType)', name:'rewardType', placeholder:'MEMBERSHIP/CRAWLER/EMPTY', default:'CRAWLER'},
-         {label:'奖励数量(rewardAmount)', name:'rewardAmount', placeholder:'爬虫次数填数量', default:'10'},
-         {label:'会员天数(rewardDays)', name:'rewardDays', placeholder:'MEMBERSHIP类型填', default:''},
-         {label:'会员等级(rewardLevel)', name:'rewardLevel', placeholder:'PRO/ULTRA', default:''},
-         {label:'概率权重(probabilityWeight)', name:'probabilityWeight', placeholder:'权重越大越容易中', default:'5'},
+         {label:'奖品名称(name)', name:'name', placeholder:'高级会员3天', default:'高级会员3天'},
+         {label:'奖励类型(rewardType)', name:'rewardType', placeholder:'MEMBERSHIP/CRAWLER/EMPTY', default:'MEMBERSHIP'},
+         {label:'会员天数(rewardDays)', name:'rewardDays', placeholder:'3', default:'3'},
+         {label:'会员等级(rewardLevel)', name:'rewardLevel', placeholder:'PRO/ULTRA', default:'PRO'},
+         {label:'爬虫次数(rewardAmount)', name:'rewardAmount', placeholder:'CRAWLER类型时填写', default:'0'},
+         {label:'概率权重(probabilityWeight)', name:'probabilityWeight', placeholder:'权重越大越容易中', default:'20'},
          {label:'启用(enabled)', name:'enabled', placeholder:'0停用/1启用', default:'1'},
-         {label:'排序(sort)', name:'sort', placeholder:'0', default:'6'}
+         {label:'排序(sort)', name:'sort', placeholder:'0', default:'3'}
         ], true, 'adminActivityLotteryPrize', '更新奖品池中的奖品配置')}
     ${testSection('admin-activity-lottery-prize-delete', '删除奖品', 'DELETE', 'delete', '/api/admin/activity/lottery/prizes/{id}', '需认证', 'auth-required',
         [{label:'奖品ID(id)', name:'id', placeholder:'需删除的奖品ID', default:''}], true, null, '从奖品池中删除指定奖品')}`;
@@ -896,9 +1025,10 @@ function validate_adminCheckinStats(result) { return result.data?.code === 200 &
 function validate_adminCheckinRecords(result) { return result.data?.code === 200 && result.data?.data?.records !== undefined; }
 function validate_adminCheckinUserRecords(result) { return result.data?.code === 200 && Array.isArray(result.data?.data); }
 
-function validate_activityInviteStatus(result) { return result.data?.code === 200 && result.data?.data?.active !== undefined; }
-function validate_activityCheckinStatus(result) { return result.data?.code === 200 && result.data?.data?.active !== undefined; }
-function validate_activityLotteryStatus(result) { return result.data?.code === 200 && result.data?.data?.active !== undefined; }
+function validate_activityInviteStatus(result) { return result.data?.code === 200 && result.data?.data?.enabled !== undefined; }
+function validate_activityCheckinStatus(result) { return result.data?.code === 200 && result.data?.data?.enabled !== undefined; }
+function validate_activityLotteryStatus(result) { return result.data?.code === 200 && result.data?.data?.enabled !== undefined; }
+function validate_activityLotteryPrizes(result) { return result.data?.code === 200 && Array.isArray(result.data?.data); }
 function validate_activityLotteryDraw(result) { return result.data?.code === 200 && result.data?.data?.prizeName !== undefined; }
 function validate_adminActivityInviteConfig(result) { return result.data?.code === 200 && result.data?.data?.id; }
 function validate_adminActivityInviteRevoke(result) { return result.data?.code === 200 && result.data?.data !== undefined; }