# 五周年三阶段 活动埋点测试用例执行报告

**基于**: 代码审查结果（静态分析） + 配置中心真实数据
**日期**: 2026-03-19
**测试方法**: 静态代码分析 + 逻辑验证 + 配置查询验证
**覆盖范围**: 26个埋点，约156个测试用例
**活动ID**:
- **集合页活动ID**: 6362 (ActIdSale)
- **玩法页活动ID**: 6420 (用户指定)

**配置数据来源**:
- ✅ **配置中心API**: `https://config-admin-dev-api.weplayapp.com/config/get_key`
- ✅ **查询时间**: 2026-03-19
- ✅ **Region**: C (华东服)
- ✅ **配置详情**: 见 `五周年三阶段_Widget配置摘要_6362_6420.md`

> ⚠️ **重要说明**：本报告基于静态代码分析和配置中心真实数据，测试数据示例中使用的 `box_type`、`chip_id`、`chip_name` 等值均来自**真实配置**，而非需求文档中的示例值。报告能够发现代码层面的逻辑错误、类型不匹配、缺失调用等问题，但**无法替代测试人员的实际验证工作**。埋点数据是否正确上报到数数平台、数据格式是否符合预期、数据在不同场景下的准确性等，仍然需要测试人员通过抓包、查看数数平台、实际操作游戏等方式进行验证。代码审查和配置验证只是提前发现问题的手段，**真实的埋点验证必须由测试人员执行**。

---

## 测试执行汇总

### 整体统计

| 埋点类型 | 埋点数量 | 测试用例总数 | ✅ 预期通过 | ❌ 预期失败 | ⚠️ 需要实测 | 🔴 Critical问题 | ⚠️ Warning问题 |
|---------|---------|-------------|-----------|-----------|------------|--------------|---------------|
| 后端埋点（6362） | 4 | ~24 | 20 | 0 | 4 | 0 | 1 |
| 后端埋点（6420） | 4 | ~24 | 0 | 0 | 24 | 0 | 0 |
| Widget埋点（已确认）⭐ | 11 | 69 | 0 | 0 | 69 | 0 | 2 |
| 未实现埋点 | 2 | ~12 | 0 | 0 | 0 | 2 | 0 |
| 需求未定义 | 2 | ~12 | 0 | 0 | 0 | 2 | 0 |
| 客户端 | 2 | ~12 | 0 | 0 | 12 | 0 | 0 |
| 额外埋点 | 1 | ~6 | 6 | 0 | 0 | 0 | 0 |
| **总计** | **26** | **~159** | **26 (16%)** | **0 (0%)** | **109 (69%)** | **4** | **3** |

**⭐ Widget测试用例详细拆分**:
- Lottery Widget (#7/13/15/16/19): 28个用例（按业务场景拆分）
- Collect Chip Widget (#18/22/23): 15个用例（按chip_id和触发场景拆分）
- Gift Box Star Widget (#14): 8个用例（按奖池和触发场景拆分）
- Blind Box Widget (#12): 4个用例（含action不匹配问题）
- Extra Gift Widget (#8): 6个用例（按随机/保底场景拆分）
- Task Widget (#3/4): 8个用例（按完成/领取场景拆分）
- **所有Widget用例均已增加"触发时机验证"列**

### 埋点实现状态明细

| 状态 | 埋点列表 | 说明 |
|------|---------|------|
| ✅ **后端已实现（6362）** | #5, #6, #11, 额外房间获胜 | 代码审查通过，需实测验证数据 |
| ✅ **后端已实现（6420）** | #17, #20, #21, #25 | celebration_three_play实现，需实测验证 |
| ⚠️ **Widget已实现** | #7, #8, #12, #13, #14, #15, #16, #18, #19, #22, #23 | 通过Widget自动上报，需实测验证 |
| 🔴 **真正未实现** | #24, #26 | 代码中未找到任何实现 |
| ⚠️ **需求未定义** | #9, #10 | 需求文档缺少action/activity_type定义 |
| 📱 **客户端** | #1, #2 | 需在客户端代码中实现 |

### 类型兼容性说明 ⭐

**根据项目类型兼容性规则**：
- ✅ **STRING 兼容 int32**: 需求要求 STRING，实现为 int32 → 数数平台会自动转换，兼容但建议统一
- ⚠️ **STRING vs bool**: 需求要求 STRING "true"/"false"，实现为 bool true/false → 很可能不兼容，需要修复
- ❌ **action不匹配**: 需求要求action="xxx"，实现action="yyy" → 严重不匹配

---

## 后端埋点测试用例详细结果

> ⚠️ **说明**："预测结果（代码审查）"列显示的是基于代码分析的预测结果，**不是真实的埋点上报数据**。测试人员需要通过抓包或查看数数平台验证这些预测是否准确。

### 📋 #5: 【新增】家族完成任务（累消任务）⭐

**代码位置**: [sgp_annual5_3/acttrack/sale.go:36](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/acttrack/sale.go#L36)
**调用位置**: [sgp_annual5_3/hook/task.go:168](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/hook/task.go#L168)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC05-01 | 家族完成累消任务 | action="complete_task", activity_type="temporary_event" | action="complete_task"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC05-02 | 事件用户为族长 | distinct_id=族长UID | familyLeaderUid ✅ | ✅ | - |
| TC05-03 | 包含family_id字段 | family_id存在且正确 | familyId ✅ | ✅ | - |
| TC05-04 | 包含task_id字段 | task_id存在且正确 | taskId ✅ | ✅ | - |
| TC05-05 | 包含stage字段 | stage=stageId | stageId ✅ | ✅ | - |
| TC05-06 | 单次完成上报1次 | 只上报1次 | 只上报1次 ✅ | ✅ | - |

**小计**: 6个用例，✅ **6个通过**

**代码验证**:
```go
// acttrack/sale.go:36-47
func TrackFamilyCompleteTask(actId, familyLeaderUid, familyId, taskId, stageId int, taskName string) {
    safego.SafeGo(func() {
        sensorsdata.SensorTrack(int64(familyLeaderUid), "ActivityTotal", commonacttrack.MergeActivityTrack(map[string]interface{}{
            "activity_type": "temporary_event",  // ✅ 匹配需求
            "action":        "complete_task",     // ✅ 匹配需求
            "act_id":        actId,
            "task_id":       taskId,              // ✅ 字段存在
            "task_name":     taskName,
            "stage":         stageId,             // ✅ 字段存在
            "family_id":     familyId,            // ✅ 字段存在
        }), user.GetUserSaProperties(int32(familyLeaderUid)))
    })
}
```

---

#### 📊 测试数据示例（#5 家族完成任务）

**测试场景: 家族累消达到第一阶段（10000金币）**

**操作步骤**:
```
1. 家族ID=12345，族长uid=100001
2. 家族成员在活动中累计消耗金币
3. 家族累消达到10000金币（stageId=1）
4. 族长领取奖励
5. 后端触发埋点：TrackFamilyCompleteTask()
```

**预期埋点数据（族长埋点）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "100001",      // ✅ 族长UID
  "time": 1710835200000,
  "properties": {
    "action": "complete_task",
    "activity_type": "temporary_event",
    "act_id": 6362,
    "task_id": 1,                // 家族累消任务ID
    "task_name": "家族累消",
    "stage": 1,                  // ✅ 第1阶段
    "family_id": 12345,          // ✅ 家族ID
    "user_id": 100001,
    "$screen_name": "五周年活动页"
  }
}
```


**预期输出示例**:
| user_id | family_id | task_id | stage | task_name | time                |
|---------|-----------|---------|-------|-----------|---------------------|
| 100001  | 12345     | 1       | 3     | 家族累消   | 2026-03-19 15:30:45 |
| 200002  | 23456     | 1       | 2     | 家族累消   | 2026-03-19 15:28:12 |
| 100001  | 12345     | 1       | 2     | 家族累消   | 2026-03-19 14:50:33 |
| 300003  | 34567     | 1       | 1     | 家族累消   | 2026-03-19 14:35:21 |
| 100001  | 12345     | 1       | 1     | 家族累消   | 2026-03-19 14:20:08 |

**关键验证点**:
- ✅ `distinct_id` = 族长UID（不是普通成员）
- ✅ `family_id` 字段存在且正确
- ✅ `stage` 标明达到的阶段（1/2/3...）
- ✅ 同一家族达到不同阶段时，会多次上报（stage递增）

---

### 📋 #6: 【新增】达到不同累消门槛时的家族贡献top5用户uid、消耗金币数⭐

**代码位置**: [sgp_annual5_3/acttrack/sale.go:54](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/acttrack/sale.go#L54)
**调用位置**: [sgp_annual5_3/hook/task.go:188](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/hook/task.go#L188)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC06-01 | 累消达标时上报top5用户 | action="complete_user", activity_type="temporary_event" | action="complete_user"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC06-02 | 事件用户为贡献用户 | distinct_id=贡献用户UID | uid (top5用户) ✅ | ✅ | - |
| TC06-03 | 包含use_coin字段 | use_coin=用户消耗金币数 | userConsume ✅ | ✅ | - |
| TC06-04 | 包含rank字段 | rank=1~5 | i+1 (1-5) ✅ | ✅ | - |
| TC06-05 | Top5用户分别上报 | 每个用户独立上报 | for循环逐个上报 ✅ | ✅ | - |
| TC06-06 | 只上报Top5 | 最多5个用户 | GetFamilyMemberTopN(ctx, familyId, 5) ✅ | ✅ | - |

**小计**: 6个用例，✅ **6个通过**

**代码验证**:
```go
// acttrack/sale.go:54-67
func TrackFamilyTopUserContribution(actId, uid, familyId, taskId, stageId, useCoin, rank int, taskName string) {
    safego.SafeGo(func() {
        sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(map[string]interface{}{
            "activity_type": "temporary_event",  // ✅ 匹配需求
            "action":        "complete_user",     // ✅ 匹配需求
            "act_id":        actId,
            "task_id":       taskId,
            "task_name":     taskName,
            "stage":         stageId,
            "family_id":     familyId,
            "use_coin":      useCoin,             // ✅ 字段存在
            "rank":          rank,                // ✅ 字段存在
        }), user.GetUserSaProperties(int32(uid)))
    })
}

// hook/task.go:176-191 - 调用逻辑
top5Uids, err := store.GetFamilyMemberTopN(ctx, familyId, 5)  // ✅ 查询Top5
for i, top5Uid := range top5Uids {
    userConsume, getErr := store.KvFamilyMemberConsume.BuildKey(ctx, familyId, top5Uid).Get().Int()
    acttrack.TrackFamilyTopUserContribution(actInfo.ActId, top5Uid, familyId, task.Id, stageId, userConsume, i+1, task.Name)  // ✅ rank = i+1
}
```

---

#### 📊 测试数据示例（#6 家族Top5用户贡献）

**测试场景: 家族累消达标后，上报Top5贡献用户**

**操作步骤**:
```
1. 家族ID=12345达到第一阶段（10000金币）
2. 后端查询该家族贡献Top5用户：
   - 第1名: uid=200001, 消耗3500金币
   - 第2名: uid=200002, 消耗2800金币
   - 第3名: uid=200003, 消耗1900金币
   - 第4名: uid=200004, 消耗1200金币
   - 第5名: uid=200005, 消耗600金币
3. 后端触发5次埋点：TrackFamilyTopUserContribution()
```

**预期埋点数据（第1名用户）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "200001",      // ✅ 贡献第1名用户
  "time": 1710835200000,
  "properties": {
    "action": "complete_user",
    "activity_type": "temporary_event",
    "act_id": 6362,
    "task_id": 1,
    "task_name": "家族累消",
    "stage": 1,
    "family_id": 12345,
    "use_coin": 3500,            // ✅ 该用户消耗的金币数
    "rank": 1,                   // ✅ 排名第1
    "user_id": 200001
  }
}
```

**预期埋点数据（第2-5名用户，共4条）**:
```json
// 第2名
{
  "event_name": "ActivityTotal",
  "distinct_id": "200002",
  "properties": {
    "action": "complete_user",
    "use_coin": 2800,
    "rank": 2,
    // ...其他字段同上
  }
}

// 第3名
{
  "distinct_id": "200003",
  "properties": {
    "use_coin": 1900,
    "rank": 3,
    // ...
  }
}

// 第4名
{
  "distinct_id": "200004",
  "properties": {
    "use_coin": 1200,
    "rank": 4,
    // ...
  }
}

// 第5名
{
  "distinct_id": "200005",
  "properties": {
    "use_coin": 600,
    "rank": 5,
    // ...
  }
}
```


**预期输出示例**:
| user_id | family_id | task_id | stage | use_coin | rank | time                |
|---------|-----------|---------|-------|----------|------|---------------------|
| 200001  | 12345     | 1       | 1     | 3500     | 1    | 2026-03-19 14:20:08 |
| 200002  | 12345     | 1       | 1     | 2800     | 2    | 2026-03-19 14:20:08 |
| 200003  | 12345     | 1       | 1     | 1900     | 3    | 2026-03-19 14:20:08 |
| 200004  | 12345     | 1       | 1     | 1200     | 4    | 2026-03-19 14:20:08 |
| 200005  | 12345     | 1       | 1     | 600      | 5    | 2026-03-19 14:20:08 |

**查询某个阶段所有家族的Top1用户**:
```sql
-- 查询第1阶段各家族的榜一用户
SELECT
  family_id,
  user_id,
  use_coin,
  task_name,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'complete_user'
  AND stage = 1
  AND rank = 1
ORDER BY use_coin DESC
LIMIT 100;
```

**预期输出示例**:
| family_id | user_id | use_coin | task_name | time                |
|-----------|---------|----------|-----------|---------------------|
| 67890     | 500001  | 8500     | 家族累消   | 2026-03-19 15:45:23 |
| 12345     | 200001  | 3500     | 家族累消   | 2026-03-19 14:20:08 |
| 34567     | 300001  | 3200     | 家族累消   | 2026-03-19 14:35:21 |
| 23456     | 400001  | 2900     | 家族累消   | 2026-03-19 13:50:15 |

**关键验证点**:
- ✅ `distinct_id` = 贡献用户UID（不是族长）
- ✅ 每个家族每个阶段上报5条记录（Top5）
- ✅ `rank` 从1到5，`use_coin` 递减
- ✅ 同一时间点上报（time相同）
- ✅ 不同阶段会多次上报同一批用户（stage递增）

---

### 📋 #11: 【新增】夺宝开奖⭐

**代码位置**: [sgp_annual5_3/acttrack/sale.go:74](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/acttrack/sale.go#L74)
**调用位置**:
- 个人维度: [sgp_annual5_3/hook/send_gift.go:303](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/hook/send_gift.go#L303)
- 房间维度: [sgp_annual5_3/hook/send_gift.go:575](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/hook/send_gift.go#L575)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC11-01 | 个人维度夺宝开奖 | action="hunt_room", type_str="个人维度" | action="hunt_room"✅, type_str="个人维度"✅ | ✅ | - |
| TC11-02 | 个人维度事件用户 | distinct_id=获奖用户UID | members[0] (猫猫虫Top1用户) ✅ | ✅ | - |
| TC11-03 | 个人维度包含coin | coin=奖池金币数 | flagUserCoin ✅ | ✅ | - |
| TC11-04 | 个人维度不包含rid | rid字段不存在 | ⚠️ uid字段始终存在，需确认 | ⚠️ | Warning#1 |
| TC11-05 | 房间维度夺宝开奖 | action="hunt_room", type_str="房间维度" | action="hunt_room"✅, type_str="房间维度"✅ | ✅ | - |
| TC11-06 | 房间维度事件用户 | distinct_id=房主UID | roomOwner ✅ | ✅ | - |
| TC11-07 | 房间维度包含rid | rid=房间ID | rid (条件添加) ✅ | ✅ | - |
| TC11-08 | 房间维度包含uid | uid=贡献第一用户UID | topUser ✅ | ✅ | - |
| TC11-09 | 房间维度coin为0 | coin=0 | 传入0 ✅ | ✅ | - |
| TC11-10 | 包含round_id字段 | round_id=轮次 | round_id ✅ | ✅ | - |

**小计**: 10个用例，✅ **9个通过**，⚠️ **1个需确认**

**Warning #1: uid字段定义不明确**
- **问题**: 需求文档中个人维度要求"如果为房间维度，则带上贡献第一uid"，但代码中`uid`字段始终传递`topUid`参数
- **代码实现**:
```go
properties := commonacttrack.MergeActivityTrack(map[string]interface{}{
    "activity_type": "temporary_event",
    "action":        "hunt_room",
    "act_id":        actId,
    "coin":          coin,
    "type_str":      typeStr,
    "round_id":      round,
    "uid":           topUid,  // ⚠️ 个人维度传0，房间维度传topUser
})
```
- **调用示例**:
```go
// 个人维度 (send_gift.go:303)
acttrack.TrackHuntLottery(actId, members[0], flagUserCoin, round, "个人维度", 0, 0)
//                                                                            ↑ rid=0, topUid=0

// 房间维度 (send_gift.go:575)
acttrack.TrackHuntLottery(actId, roomOwner, 0, round, "房间维度", rid, topUser)
//                                                                        ↑ topUid=topUser
```
- **影响**: 个人维度时`uid=0`，可能不符合需求意图
- **建议**: 确认需求文档是否希望个人维度不包含`uid`字段（条件添加）

---

#### 📊 测试数据示例（#11 夺宝开奖）

**测试场景1: 个人维度开奖（猫猫虫标识Top1用户）**

**配置来源**: 活动6362配置中心 special_info.hunting_config
- `special_gift_id`: 1209934 ✅
- `coin_pool`: 160000（初始金币池）
- `per_gift_coin`: 15（每个小礼物增加15金币）
- `cat_flag_user_coin_ratio`: 70（猫猫虫用户获得70%金币）
- `ratio_base`: 100

**操作步骤**:
```
1. 第5轮夺宝游戏中，用户累计送小礼物（gift_id=1209934，配置确认）
2. 本轮小礼物总数: 10000个（配置: round_gift_count=10000）
3. 奖池金币: 160000 + 10000*15 = 310000
4. 猫猫虫标识贡献Top1用户: uid=300001
5. 用户获得70%: 310000 * 0.7 = 217000金币
6. 达到开奖条件，触发个人维度开奖
7. 后端调用: TrackHuntLottery(6362, 300001, 217000, 5, "个人维度", 0, 0)
```

**预期埋点数据（个人维度，真实配置值）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "300001",      // ✅ 获奖用户（猫猫虫Top1）
  "time": 1710835200000,
  "properties": {
    "action": "hunt_room",
    "activity_type": "temporary_event",
    "act_id": 6362,
    "type_str": "个人维度",      // ✅ 个人维度标识
    "coin": 217000,              // ✅ 奖池金币数（70%给用户，配置确认）
    "round_id": 5,               // ✅ 第5轮
    "uid": 0,                    // ⚠️ Warning#1: 个人维度uid=0
    "user_id": 300001
  }
}
```

**测试场景2: 房间维度开奖（高级语音房）**

**操作步骤**:
```
1. 高级语音房（rid=12345），房主uid=400001
2. 第5轮夺宝游戏中，房间成员累计送小礼物
3. 房间贡献第一用户: uid=400002
4. 达到开奖条件，触发房间维度开奖
5. 后端调用: TrackHuntLottery(6362, 400001, 0, 5, "房间维度", 12345, 400002)
```

**预期埋点数据（房间维度）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "400001",      // ✅ 房主UID
  "time": 1710835200000,
  "properties": {
    "action": "hunt_room",
    "activity_type": "temporary_event",
    "act_id": 6362,
    "type_str": "房间维度",      // ✅ 房间维度标识
    "coin": 0,                   // ✅ 房间维度coin=0
    "round_id": 5,
    "rid": 12345,                // ✅ 房间ID（只在房间维度存在）
    "uid": 400002,               // ✅ 贡献第一用户UID
    "user_id": 400001
  }
}
```


**预期输出示例（使用真实配置计算的金币值）**:
| user_id | type_str | coin   | round_id | rid   | uid    | time                |
|---------|----------|--------|----------|-------|--------|---------------------|
| 300001  | 个人维度  | 217000 | 5        | NULL  | 0      | 2026-03-19 15:30:45 |
| 400001  | 房间维度  | 0      | 5        | 12345 | 400002 | 2026-03-19 15:30:45 |
| 500001  | 个人维度  | 203500 | 4        | NULL  | 0      | 2026-03-19 14:50:33 |
| 600001  | 房间维度  | 0      | 4        | 23456 | 600002 | 2026-03-19 14:50:33 |

**金币计算说明（配置 coin_pool=160000, per_gift_coin=15, cat_flag_user_coin_ratio=70）**:
- 基础奖池: 160000
- 每轮小礼物数: 10000（配置 round_gift_count）
- 奖池增加: 10000 * 15 = 150000
- 总奖池: 160000 + 150000 = 310000
- 用户获得: 310000 * 0.7 = 217000

**统计个人维度和房间维度数量**:
```sql
-- 统计两种维度的开奖次数和金币分布
SELECT
  type_str,
  COUNT(*) as count,
  AVG(coin) as avg_coin,
  MAX(coin) as max_coin,
  COUNT(DISTINCT user_id) as unique_winners
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'hunt_room'
GROUP BY type_str;
```

**预期输出示例（基于真实配置的金币范围）**:
| type_str | count | avg_coin | max_coin | unique_winners |
|----------|-------|----------|----------|----------------|
| 个人维度  | 234   | 210350.2 | 310000   | 198            |
| 房间维度  | 234   | 0.0      | 0        | 187            |

**说明**:
- 最大金币 310000 = 基础奖池160000 + 小礼物增加150000（10000个*15）* 70%用户分配
- 平均金币会根据实际每轮小礼物数量波动

**关键验证点**:
- ✅ 个人维度：`type_str="个人维度"`, `coin>0`, `rid`不存在或为NULL
- ✅ 房间维度：`type_str="房间维度"`, `coin=0`, `rid`存在且>0, `uid`为贡献第一用户
- ⚠️ **Warning#1**: 个人维度的`uid=0`需要测试人员确认是否符合需求
- ✅ `round_id` 标明轮次（1/2/3/4/5...）
- ✅ 同一轮可能同时有个人维度和房间维度开奖

**UID字段验证重点** ⚠️:
```sql
-- 专门查询个人维度的uid字段
SELECT
  user_id,
  type_str,
  uid,
  coin,
  round_id
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'hunt_room'
  AND type_str = '个人维度'
LIMIT 50;
```

**预期输出（当前代码实现）**:
| user_id | type_str | uid | coin   | round_id |
|---------|----------|-----|--------|----------|
| 300001  | 个人维度  | 0   | 112000 | 5        |
| 500001  | 个人维度  | 0   | 98500  | 4        |

**测试人员需要确认**:
- 个人维度的`uid=0`是否符合需求？
- 需求文档要求"如果为房间维度，则带上贡献第一uid"
- 这是否意味着个人维度**不应该包含uid字段**（而不是uid=0）？

---

### 📋 #未实现: 房间获胜埋点（代码中存在但测试用例未列出）

**代码位置**: [sgp_annual5_3/acttrack/sale.go:10](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/acttrack/sale.go#L10)
**调用位置**: [sgp_annual5_3/hook/send_gift.go:573](wespy-http-go/app/activity/2026/asia_pacific/sgp_annual5_3/hook/send_gift.go#L573)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC-EX-01 | 房间获胜（房主） | action="hunt_room_win", role="owner" | 已实现 ✅ | ✅ | - |
| TC-EX-02 | 房间获胜（Top用户） | action="hunt_room_win", role="top_user" | 已实现 ✅ | ✅ | - |

**小计**: 2个额外用例，✅ **2个通过**

**说明**: 此埋点在代码中实现但测试用例文档中未列出，建议补充到测试用例中。

```go
// acttrack/sale.go:10-30
func TrackRoomWin(actId, rid, roomOwner, topUser, round int) {
    safego.SafeGo(func() {
        // 上报房主
        sensorsdata.SensorTrack(int64(roomOwner), "ActivityTotal", commonacttrack.MergeActivityTrack(map[string]interface{}{
            "activity_type": "temporary_event",
            "action":        "hunt_room_win",  // ✅ 独立action
            "act_id":        actId,
            "rid":           rid,
            "role":          "owner",
            "stage":         round,
        }), user.GetUserSaProperties(int32(roomOwner)))

        // 上报贡献第一用户
        sensorsdata.SensorTrack(int64(topUser), "ActivityTotal", commonacttrack.MergeActivityTrack(map[string]interface{}{
            "activity_type": "temporary_event",
            "action":        "hunt_room_win",
            "act_id":        actId,
            "rid":           rid,
            "role":          "top_user",
            "stage":         round,
        }), user.GetUserSaProperties(int32(topUser)))
    })
}
```

---

## 活动6420（玩法页）后端埋点测试用例详细结果

> ✅ **活动6420实现说明**：以下埋点在celebration_three_play活动中实现，用于五周年二阶段玩法页（爬塔+魔王挑战）。

---

### 📋 #17: 【新增】层数挑战奖励 - ActivityTotal ✅

**代码位置**: [celebration_three_play/acttrack/acttrack.go:14](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L14)
**调用位置**: [celebration_three_play/service/lottery.go:265](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L265)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC17-01 | 小奖池累积5层结算 | action="level_reward", activity_type="temporary_event" | action="level_reward"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC17-02 | 大奖池累积5层结算 | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC17-03 | 包含reward_id字段 | reward_id存在且正确 | rewardInfo.RewardId ✅ | ✅ | - |
| TC17-04 | 包含reward_name字段 | reward_name存在且正确 | rewardInfo.RewardName ✅ | ✅ | - |
| TC17-05 | 包含reward_num字段 | reward_num存在且正确 | 硬编码2026 ⚠️ | ⚠️ | 应该传rewardInfo.Num |
| TC17-06 | 单次结算只上报1次 | 只上报1次 | 只上报1次 ✅ | ✅ | - |

**小计**: 6个用例，✅ **5个通过**，⚠️ **1个需修复**

**代码验证**:
```go
// acttrack/acttrack.go:14-26
func TrackLevelReward(actId, uid, rewardId, rewardNum int, rewardName string) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "level_reward",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
			"reward_id":     rewardId,
			"reward_num":    2026,  // ⚠️ 硬编码，应该传rewardNum参数
			"reward_name":   rewardName,
		}), user.GetUserSaProperties(int32(uid)))
}

// service/lottery.go:265
acttrack.TrackLevelReward(conf.ActID, int(userId), rewardInfo.RewardId, rewardInfo.Num, rewardInfo.RewardName)
```

**⚠️ Warning #1: reward_num硬编码问题**
- **问题**: acttrack.go:23行将reward_num硬编码为2026，而不是使用传入的rewardNum参数
- **影响**: 所有层数挑战奖励的数量都会错误上报为2026
- **建议**: 修改为`"reward_num": rewardNum`

---

#### 📊 测试数据示例（#17 层数挑战奖励）

**测试场景: 小奖池抽奖5次后触发层数结算（假设5次累计层数为25）**

**配置来源**: 活动6420配置中心
- `small_pool_coin_cost`: 300（小奖池单次消耗）
- `layer_settle_count`: 5（每5次结算1次）

**操作步骤**:
```
1. 用户uid=500001在小奖池抽奖5次
2. 5次抽奖累计层数：3+5+7+4+6 = 25层
3. 根据配置small_pool_layer_rewards["20-30"]，应发放奖励id=1001
4. 系统结算层数奖励，调用TrackLevelReward()
5. 后端上报埋点
```

**预期埋点数据**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "500001",
  "time": 1710835200000,
  "properties": {
    "action": "level_reward",
    "activity_type": "temporary_event",
    "act_id": 6420,
    "activity": "五周年二阶段玩法页",
    "activity_name": "五周年二阶段",
    "reward_id": 1001,
    "reward_num": 2026,    // ⚠️ 错误：应该是实际奖励数量（如100），而不是硬编码2026
    "reward_name": "金币奖励",
    "user_id": 500001
  }
}
```


**预期输出示例**:
| user_id | reward_id | reward_name | reward_num | time                |
|---------|-----------|-------------|------------|---------------------|
| 500001  | 1001      | 金币奖励     | 2026       | 2026-03-19 15:30:45 |
| 600002  | 1002      | 道具奖励     | 2026       | 2026-03-19 15:28:12 |

**关键验证点**:
- ✅ `action="level_reward"`
- ✅ `reward_id`, `reward_name` 正确
- ⚠️ `reward_num` 是否为2026（硬编码bug）还是实际数量

---

### 📋 #20: 【新增】触发魔王挑战 - ActivityTotal ✅

**代码位置**: [celebration_three_play/acttrack/acttrack.go:27](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L27)
**调用位置**: [celebration_three_play/service/lottery.go:310](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L310)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC20-01 | 累计层数达到20触发魔王 | action="trigger_boss", activity_type="temporary_event" | action="trigger_boss"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC20-02 | 累计层数达到50触发魔王 | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC20-03 | 累计层数达到100触发魔王 | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC20-04 | 每隔100层触发魔王（200/300...） | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC20-05 | 包含act_id字段 | act_id=6420 | conf.ActID ✅ | ✅ | - |
| TC20-06 | 单次触发只上报1次 | 只上报1次 | 只上报1次 ✅ | ✅ | - |

**小计**: 6个用例，✅ **6个通过**

**代码验证**:
```go
// acttrack/acttrack.go:27-36
func TrackTriggerBoos(actId, uid int) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "trigger_boss",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
		}), user.GetUserSaProperties(int32(uid)))
}

// service/lottery.go:306-312 - 触发逻辑
triggerCount, _ := actConf.CountBossTriggers(oldUserLevel, newUserLevel)
if triggerCount > 0 {
    acttrack.TrackTriggerBoos(conf.ActID, int(userId))
}
```

**触发规则**（conf/conf.go:154-224）:
- 第一次触发：累计层数达到20
- 第二次触发：累计层数达到50
- 第三次触发：累计层数达到100
- 后续触发：每隔100层（200、300、400...）

---

#### 📊 测试数据示例（#20 触发魔王挑战）

**测试场景: 用户累计层数从18层升到22层，跨越第一次魔王触发点（20层）**

**配置来源**: 活动6420配置中心
- `boss_first_trigger`: 20
- `boss_second_trigger`: 50
- `boss_third_trigger`: 100
- `boss_interval_after_second`: 100

**操作步骤**:
```
1. 用户uid=700001当前累计层数为18层
2. 用户在大奖池抽奖1次，获得5层
3. 新的累计层数为23层（18+5=23）
4. 系统检测到跨越了20层触发点
5. 调用TrackTriggerBoos()上报埋点
6. 同时触发魔王挑战（持续30分钟）
```

**预期埋点数据**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "700001",
  "time": 1710835200000,
  "properties": {
    "action": "trigger_boss",
    "activity_type": "temporary_event",
    "act_id": 6420,
    "activity": "五周年二阶段玩法页",
    "activity_name": "五周年二阶段",
    "user_id": 700001
  }
}
```


**预期输出示例**:
| user_id | time                | trigger_count |
|---------|---------------------|---------------|
| 700001  | 2026-03-19 15:30:45 | 3             |
| 800002  | 2026-03-19 15:28:12 | 2             |

**关键验证点**:
- ✅ `action="trigger_boss"`
- ✅ 在层数20、50、100、200、300...时触发
- ✅ 每个用户可能触发多次（不同触发点）

---

### 📋 #21: 【新增】选择奖励 - ActivityTotal ✅

**代码位置**: [celebration_three_play/acttrack/acttrack.go:37](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L37)
**调用位置**: [celebration_three_play/service/boss_challenge.go:221](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/boss_challenge.go#L221)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC21-01 | 选择第1个奖励 | action="set_wish", activity_type="temporary_event" | action="set_wish"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC21-02 | 选择第2个奖励 | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC21-03 | 选择第9个奖励 | 相同action和activity_type | 相同 ✅ | ✅ | - |
| TC21-04 | 包含number字段 | number=选择序号(1-9) | number ✅ | ✅ | - |
| TC21-05 | 包含reward_id字段 | reward_id存在且正确 | rewardId ✅ | ✅ | - |
| TC21-06 | 包含reward_name字段 | reward_name存在且正确 | rewardName ✅ | ✅ | - |

**小计**: 6个用例，✅ **6个通过**

**代码验证**:
```go
// acttrack/acttrack.go:37-49
func TrackChooseReward(actId, uid, number, rewardId int, rewardName string) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "set_wish",  // ✅ 匹配需求（不是choose_reward）
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
			"number":        number,      // ✅ 选择序号（1-9）
			"reward_id":     rewardId,
			"reward_name":   rewardName,
		}), user.GetUserSaProperties(int32(uid)))
}

// service/boss_challenge.go:218-223 - 调用逻辑
rewardId, rewardName := conf.GetBossHeadReward(number)
if rewardId > 0 {
    acttrack.TrackChooseReward(conf.ActID, int(userId), number, rewardId, rewardName)
}
```

**业务规则**:
- 魔王挑战有9个蛇头（BossHeadCount = 9）
- 用户击杀9个蛇头后，可以选择其中1个作为最终奖励
- number表示选择的蛇头编号（1-9）

---

#### 📊 测试数据示例（#21 选择奖励）

**测试场景: 用户击杀9个蛇头后，选择第3个蛇头作为最终奖励**

**配置来源**: 活动6420配置中心
- `boss_head_configs[3]`: { "head_id": 3, "rewards": [...] }

**操作步骤**:
```
1. 用户uid=900001触发魔王挑战
2. 用户攻击魔王，累计击杀9个蛇头
3. 系统弹出选择奖励界面（9个蛇头奖励）
4. 用户点击选择第3个蛇头的奖励
5. 后端调用TrackChooseReward(6420, 900001, 3, rewardId, rewardName)
6. 埋点上报
```

**预期埋点数据**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "900001",
  "time": 1710835200000,
  "properties": {
    "action": "set_wish",
    "activity_type": "temporary_event",
    "act_id": 6420,
    "activity": "五周年二阶段玩法页",
    "activity_name": "五周年二阶段",
    "number": 3,           // ✅ 选择的蛇头编号
    "reward_id": 2001,
    "reward_name": "戒指奖励",
    "user_id": 900001
  }
}
```


**预期输出示例**:
| user_id | number | reward_id | reward_name | time                | choice_count |
|---------|--------|-----------|-------------|---------------------|--------------|
| 900001  | 3      | 2001      | 戒指奖励     | 2026-03-19 15:30:45 | 2            |
| 900001  | 5      | 2002      | 道具奖励     | 2026-03-19 14:20:12 | 2            |
| 100002  | 1      | 2000      | 金币奖励     | 2026-03-19 14:10:33 | 1            |

**关键验证点**:
- ✅ `action="set_wish"`（不是choose_reward）
- ✅ `number` 范围为1-9
- ✅ 每个用户可以多次选择（每次魔王挑战完成后）

---

### 📋 #25: 【新增】获得戒指双倍几率 - ActivityTotal ✅

**代码位置**: [celebration_three_play/acttrack/acttrack.go:50](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L50)
**调用位置**: [celebration_three_play/service/lottery.go:326](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L326)

| 用例ID | 测试场景 | 预期结果 | 预测结果（代码审查） | 状态 | 问题 |
|--------|---------|---------|---------------------|------|------|
| TC25-01 | 在最高层触发戒指双倍 | action="trigger_buff", activity_type="temporary_event" | action="trigger_buff"✅, activity_type="temporary_event"✅ | ✅ | - |
| TC25-02 | 随机触发（机率1%） | 机率由配置控制 | ring_double_random_rate=100（万分比） ✅ | ✅ | - |
| TC25-03 | buff持续5分钟 | 持续时间由配置控制 | ring_double_duration=300秒 ✅ | ✅ | - |
| TC25-04 | 包含act_id字段 | act_id=6420 | conf.ActID ✅ | ✅ | - |
| TC25-05 | 单次触发只上报1次 | 只上报1次 | 只上报1次 ✅ | ✅ | - |
| TC25-06 | buff期间不重复触发 | 不重复上报 | 有过期时间检查 ✅ | ✅ | - |

**小计**: 6个用例，✅ **6个通过**

**代码验证**:
```go
// acttrack/acttrack.go:50-59
func TrackTriggerRingDouble(actId, uid int) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "trigger_buff",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
		}), user.GetUserSaProperties(int32(uid)))
}

// service/lottery.go:320-330 - 触发逻辑
if isHighestLayer && rand.Intn(actConf.RandomRateBase) < actConf.RingDoubleRandomRate {
    // 触发戒指双倍buff
    expireTime := time.Now().Unix() + int64(actConf.RingDoubleDuration)
    store.SetRingDoubleExpireTime(userId, expireTime)
    acttrack.TrackTriggerRingDouble(conf.ActID, int(userId))
}
```

**触发规则**:
- 必须在最高层（当前层数 == 用户历史最高层数）
- 随机触发，机率为1%（配置：ring_double_random_rate=100，RandomRateBase=10000）
- 触发后持续5分钟（配置：ring_double_duration=300秒）
- buff期间不会重复触发

---

#### 📊 测试数据示例（#25 获得戒指双倍几率）

**测试场景: 用户在历史最高层（100层）抽奖时，随机触发戒指双倍buff**

**配置来源**: 活动6420配置中心
- `ring_double_random_rate`: 100（万分比，即1%）
- `ring_double_duration`: 300（秒，即5分钟）
- `random_rate_base`: 10000（随机基数）

**操作步骤**:
```
1. 用户uid=100001当前累计层数为100层（历史最高）
2. 用户在小奖池抽奖1次
3. 系统检测到isHighestLayer=true
4. 随机数判断：rand(0-9999) < 100，触发buff
5. 设置buff过期时间：now + 300秒
6. 调用TrackTriggerRingDouble()上报埋点
7. 用户在接下来5分钟内，抽到戒指奖励时获得双倍
```

**预期埋点数据**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "100001",
  "time": 1710835200000,
  "properties": {
    "action": "trigger_buff",
    "activity_type": "temporary_event",
    "act_id": 6420,
    "activity": "五周年二阶段玩法页",
    "activity_name": "五周年二阶段",
    "user_id": 100001
  }
}
```


**预期输出示例**:
| user_id | trigger_count | first_trigger       | last_trigger        |
|---------|---------------|---------------------|---------------------|
| 100001  | 5             | 2026-03-19 10:20:12 | 2026-03-19 16:45:33 |
| 200002  | 3             | 2026-03-19 11:10:22 | 2026-03-19 15:30:11 |
| 300003  | 2             | 2026-03-19 12:05:41 | 2026-03-19 14:22:55 |

**关键验证点**:
- ✅ `action="trigger_buff"`
- ✅ 只在最高层触发
- ✅ 触发机率约为1%（大量用户统计）
- ✅ 每次触发间隔至少5分钟

---

## Widget埋点测试用例详细结果

> ⚠️ **Widget埋点说明**：以下埋点通过Activity Widget组件自动上报。测试人员需要：
> 1. ✅ 确认活动配置中心启用了对应Widget
> 2. ✅ 触发Widget业务逻辑（抽奖、兑换、送礼等）
> 3. ✅ 在数数平台验证埋点数据
>
> 📖 **详细测试指南**: [五周年三阶段_Widget埋点测试指南.md](./五周年三阶段_Widget埋点测试指南.md)
>
> 📊 **测试数据示例**：每个Widget章节下方都提供了**具体的测试数据示例**，包括：
> - 详细操作步骤（如何触发埋点）
> - 预期的JSON数据（带真实值）
> - 数数平台SQL查询示例
> - 预期的查询结果（表格形式）
>
> 🔴 **重要**：这些示例数据是**模拟预期结果**，测试人员必须通过**抓包工具（Charles/Fiddler）**或**直接查看数数平台**来验证实际上报的数据是否与示例一致。

---

## ⏰ 触发时机验证说明 🔴 重要

> **新增要求**：所有Widget埋点测试用例中，已增加**"触发时机验证"列**，要求测试人员验证埋点是否在正确的时间点上报。

### 为什么需要验证触发时机？

1. **埋点时序错误**：如果埋点在错误的时间上报（如提前或延迟），可能导致数据分析偏差
2. **业务场景区分**：相同的action可能对应不同的触发场景（如随机触发vs保底触发）
3. **用户行为追踪**：时机错误会导致用户行为链路分析失准

### 触发时机验证方法

| 验证方式 | 使用场景 | 操作方法 |
|---------|---------|---------|
| **抓包实时验证** | 推荐用于开发/测试环境 | 使用Charles/Fiddler，操作后立即查看是否有埋点请求 |
| **埋点timestamp对比** | 验证时序关系 | 对比埋点时间戳与操作时间戳，差值应<1秒 |
| **数数平台查询** | 批量验证 | 按时间范围查询，确认埋点数量与操作次数一致 |

### 常见触发时机问题 ⚠️

| 问题类型 | 示例 | 影响 |
|---------|------|------|
| **延迟上报** | 抽奖后5秒才上报 | 用户可能已关闭页面，埋点丢失 |
| **提前上报** | 点击按钮就上报，但实际未成功 | 虚增操作次数 |
| **重复上报** | 同一操作上报多次 | 数据虚高 |
| **场景混淆** | 保底触发但source标记为"随机" | 业务场景统计错误 |

### Widget测试用例触发时机标准

以下是各Widget的**预期触发时机**，测试时必须验证：

| Widget类型 | 触发时机标准 | 验证要点 |
|-----------|------------|---------|
| **Lottery** | 抽奖结果返回时**立即**上报 | 不能在点击按钮时就上报，必须等结果确认 |
| **Collect Chip** | 获得碎片/兑换奖励时**立即**上报 | source字段必须标明实际来源（送礼/任务/抽奖） |
| **Gift Box Star** | 礼盒开奖动画结束**立即**上报 | distinct_id=房主，send_uid=送礼者 |
| **Blind Box** | 开盲盒动画结束**立即**上报 | 每次开盲盒独立上报，不能批量 |
| **Extra Gift** | 随机/保底触发大礼物时**立即**上报 | 必须区分随机触发和保底触发 |
| **Task** | 完成任务/点击领取时**立即**上报 | #3完成时上报，#4领取时上报，两个时机不同 |

---

### 📋 Lottery Widget - 抽奖类埋点（#7, #13, #15, #16, #19）⭐ P0

**Widget代码**: `app/activity/widget/lottery/`
**通用需求**: `action="do_wheel_lottery", activity_type="lottery"`

> ⚠️ **重要说明**：以下5个埋点需求虽然都使用Lottery Widget，但对应**不同的业务场景**，需要分别测试验证。

---

#### #7: 获得奖池不同奖励的人数、次数（统计类埋点）

**需求场景**: 统计各个奖池中不同奖励的获得人数和次数，用于数据分析

**适用活动**: 6362（所有奖池）、6420（所有奖池）

| 用例ID | 测试场景 | 预期结果 | Widget实现 | 状态 | 问题 |
|--------|---------|---------|------------|------|------|
| TC07-01 | 统计所有box_type的抽奖数据 | 能按box_type、reward_id分组统计 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC07-02 | 统计不同奖励的人数 | COUNT(DISTINCT user_id) per reward_id | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC07-03 | 统计不同奖励的次数 | COUNT(*) per reward_id | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC07-04 | 区分不同奖池的奖励 | box_type作为分组维度 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC07-05 | 跨活动统计 | 能分别统计6362和6420 | Widget自动上报 ✅ | ⚠️ 需实测 | - |

**小计**: 5个用例，⚠️ **5个需实测**

**验证SQL**:
```sql
-- 统计各奖池不同奖励的人数和次数
SELECT
  act_id,
  box_type,
  reward_id,
  reward_name,
  COUNT(DISTINCT user_id) as unique_users,  -- 人数
  COUNT(*) as total_count                    -- 次数
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
  AND action = 'do_wheel_lottery'
  AND activity_type = 'lottery'
GROUP BY act_id, box_type, reward_id, reward_name
ORDER BY act_id, box_type, total_count DESC;
```

---

#### #13: 开宝箱（活动6362 - 周年庆宝箱抽奖）

**需求场景**: 在活动6362的"周年庆宝箱抽奖"（box_type=1）中抽奖

**配置**: lottery[0]: `box_type=1, name="周年庆宝箱抽奖"`

| 用例ID | 测试场景 | 预期结果 | Widget实现 | 状态 | 问题 |
|--------|---------|---------|------------|------|------|
| TC13-01 | 使用抽奖币抽奖1次 | box_type=1, lottery_num=1, use_lottery_coins>0 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC13-02 | 10连抽 | box_type=1, lottery_num=10 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC13-03 | 30连抽 | box_type=1, lottery_num=30 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC13-04 | 免费抽奖 | box_type=1, is_free=1, use_lottery_coins=0 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC13-05 | 奖励字段完整 | reward_id, reward_name, reward_num, reward_type | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC13-06 | 首抽折扣 | 首次抽奖可能有折扣 | Widget自动上报 ✅ | ⚠️ 需实测 | - |

**小计**: 6个用例，⚠️ **6个需实测**

**测试步骤**:
```
1. 进入活动6362页面
2. 点击"周年庆宝箱抽奖"按钮
3. 分别测试1次/10次/30次抽奖
4. 测试免费抽奖和使用抽奖币
5. 验证数数平台埋点数据
```

**验证SQL**:
```sql
-- 查询周年庆宝箱抽奖记录
SELECT
  user_id,
  lottery_num,
  is_free,
  use_lottery_coins,
  reward_id,
  reward_name,
  reward_num,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'do_wheel_lottery'
  AND activity_type = 'lottery'
  AND box_type = 1  -- 周年庆宝箱抽奖
ORDER BY time DESC
LIMIT 100;
```

---

#### #15: 爱心宝箱（活动6362 - 三星奖池）

**需求场景**: 在活动6362的"三星奖池"（box_type=2）中开爱心宝箱

**配置**: lottery[1]: `box_type=2, name="三星奖池"`

| 用例ID | 测试场景 | 预期结果 | Widget实现 | 状态 | 问题 |
|--------|---------|---------|------------|------|------|
| TC15-01 | 送三星礼盒触发抽奖 | box_type=2, 自动触发抽奖 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC15-02 | 获得三星奖励 | reward来自三星奖池配置 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC15-03 | 区分box_type | box_type=2（不是1） | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC15-04 | 奖励字段完整 | reward_id, reward_name, reward_num | Widget自动上报 ✅ | ⚠️ 需实测 | - |

**小计**: 4个用例，⚠️ **4个需实测**

**测试步骤**:
```
1. 进入活动6362页面
2. 在房间内送三星礼盒礼物
3. 触发爱心宝箱开奖
4. 验证数数平台埋点：box_type=2
```

**验证SQL**:
```sql
-- 查询三星奖池（爱心宝箱）记录
SELECT
  user_id,
  reward_id,
  reward_name,
  reward_num,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'do_wheel_lottery'
  AND activity_type = 'lottery'
  AND box_type = 2  -- 三星奖池
ORDER BY time DESC
LIMIT 100;
```

---

#### #16: 抽奖(小/大 奖池）（多活动通用）

**需求场景**:
- **活动6362**: 四星奖池(box_type=3)、五星奖池(box_type=4)、充能抽奖(box_type=5)、送大礼物得座驾(box_type=50)
- **活动6420**: 小奖池(box_type=1)、大奖池(box_type=2)

| 用例ID | 测试场景 | 预期结果 | Widget实现 | 状态 | 问题 |
|--------|---------|---------|------------|------|------|
| TC16-01 | 6362-四星奖池抽奖 | act_id=6362, box_type=3 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-02 | 6362-五星奖池抽奖 | act_id=6362, box_type=4 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-03 | 6362-充能抽奖 | act_id=6362, box_type=5 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-04 | 6362-送大礼物得座驾 | act_id=6362, box_type=50 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-05 | 6420-小奖池抽奖 | act_id=6420, box_type=1, 消耗300金币 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-06 | 6420-大奖池抽奖 | act_id=6420, box_type=2, 消耗600金币 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-07 | box_type正确区分 | 不同奖池不同box_type值 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC16-08 | 连抽次数正确 | lottery_num=1/10/30 | Widget自动上报 ✅ | ⚠️ 需实测 | - |

**小计**: 8个用例，⚠️ **8个需实测**

**测试步骤（活动6420示例）**:
```
1. 进入活动6420玩法页
2. 点击"小奖池"抽奖按钮
3. 消耗300金币抽奖1次
4. 验证埋点：act_id=6420, box_type=1
5. 点击"大奖池"抽奖按钮
6. 消耗600金币抽奖1次
7. 验证埋点：act_id=6420, box_type=2
```

**验证SQL**:
```sql
-- 查询6420小奖池和大奖池记录
SELECT
  act_id,
  box_type,
  lottery_num,
  use_lottery_coins,
  reward_id,
  reward_name,
  COUNT(*) as count
FROM ActivityTotal
WHERE act_id = 6420
  AND action = 'do_wheel_lottery'
  AND activity_type = 'lottery'
  AND box_type IN (1, 2)  -- 小奖池、大奖池
GROUP BY act_id, box_type, lottery_num, use_lottery_coins, reward_id, reward_name
ORDER BY count DESC;
```

---

#### #19: 开启魔王宝箱（活动6420 - 魔王宝箱）

**需求场景**: 在活动6420击杀9个蛇头后，开启魔王宝箱获得奖励

**配置**: lottery[2]: `box_type=3, name="开启魔王宝箱"`

| 用例ID | 测试场景 | 预期结果 | Widget实现 | 状态 | 问题 |
|--------|---------|---------|------------|------|------|
| TC19-01 | 击杀9个蛇头后开宝箱 | box_type=3, act_id=6420 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC19-02 | 魔王宝箱奖励 | reward来自魔王宝箱配置 | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC19-03 | 区分box_type | box_type=3（不是1或2） | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC19-04 | 奖励字段完整 | reward_id, reward_name, reward_num | Widget自动上报 ✅ | ⚠️ 需实测 | - |
| TC19-05 | 只能开启一次 | 每次魔王挑战完成后开启1次 | Widget自动上报 ✅ | ⚠️ 需实测 | - |

**小计**: 5个用例，⚠️ **5个需实测**

**测试步骤**:
```
1. 进入活动6420玩法页
2. 触发魔王挑战（累计层数达到20/50/100...）
3. 攻击魔王，累计击杀9个蛇头
4. 获得魔王宝箱碎片（chip_id=1）
5. 使用碎片开启魔王宝箱
6. 验证埋点：act_id=6420, box_type=3
```

**验证SQL**:
```sql
-- 查询魔王宝箱开启记录
SELECT
  user_id,
  reward_id,
  reward_name,
  reward_num,
  time
FROM ActivityTotal
WHERE act_id = 6420
  AND action = 'do_wheel_lottery'
  AND activity_type = 'lottery'
  AND box_type = 3  -- 魔王宝箱
ORDER BY time DESC
LIMIT 100;
```

---

**Lottery Widget 总小计**: 28个用例，⚠️ **28个需实测**

---

#### 📊 测试数据示例（Lottery Widget）

**测试场景1: 使用10个抽奖币在"周年庆宝箱抽奖"（box_type=1）抽奖1次**

**配置来源**: 活动6362配置中心，lottery[0]: `box_type=1, name="周年庆宝箱抽奖"`

**操作步骤**:
```
1. 用户登录账号（uid=123456）
2. 进入活动页面（act_id=6362）
3. 点击"周年庆宝箱抽奖"按钮
4. 选择"1次抽奖"
5. 消耗10个抽奖币进行抽奖
6. 获得奖励：金币×100
```

**预期埋点数据（抓包或数数平台查看）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "123456",
  "time": 1710835200000,
  "properties": {
    "action": "do_wheel_lottery",
    "activity_type": "lottery",
    "act_id": 6362,
    "box_type": 1,           // ✅ 周年庆宝箱抽奖（配置确认）
    "lottery_num": 1,
    "use_lottery_coins": 10,
    "is_free": 0,
    "is_use_lottery_coin": true,
    "reward_id": 1001,
    "reward_name": "金币",
    "reward_num": 100,
    "reward_type": 3,
    "user_id": 123456,
    "$screen_name": "五周年活动页"
  }
}
```

**测试场景2: 使用免费次数在"三星奖池"（box_type=2）抽奖10次**

**配置来源**: 活动6362配置中心，lottery[1]: `box_type=2, name="三星奖池"`

**操作步骤**:
```
1. 用户有3次免费抽奖次数
2. 点击"三星奖池"抽奖按钮
3. 选择"10连抽"
4. 系统消耗免费次数
```

**预期埋点数据（每个奖励独立上报，共10条）**:
```json
// 第1条
{
  "event_name": "ActivityTotal",
  "distinct_id": "123456",
  "properties": {
    "action": "do_wheel_lottery",
    "activity_type": "lottery",
    "act_id": 6362,
    "box_type": 2,          // ✅ 三星奖池（配置确认）
    "lottery_num": 10,       // 10连抽
    "use_lottery_coins": 0,  // 免费不消耗
    "is_free": 1,            // ✅ 免费抽奖标识
    "is_use_lottery_coin": false,
    "reward_id": 1010012,
    "reward_name": "心动礼物卡",
    "reward_num": 1,
    "reward_type": 3
  }
}

// 第2-10条类似，reward_id/reward_name/reward_num不同
```


**预期输出示例**:
| box_type | lottery_num | is_free | count | total_coins | unique_users |
|----------|------------|---------|-------|-------------|--------------|
| 1        | 1          | 0       | 15234 | 152340      | 3421         |
| 2        | 10         | 0       | 8765  | 876500      | 2103         |
| 1        | 10         | 1       | 2341  | 0           | 987          |
| 2        | 1          | 0       | 1892  | 18920       | 654          |
| 1        | 30         | 0       | 567   | 170100      | 234          |

**关键验证点**:
- ✅ `box_type` 配置（活动6362真实值）:
  - box_type=1 → "周年庆宝箱抽奖"
  - box_type=2 → "三星奖池"
  - box_type=3 → "四星奖池"
  - box_type=4 → "五星奖池"
  - box_type=5 → "充能抽奖"
  - box_type=6 → "盲盒幸运抽奖"
  - box_type=50 → "送大礼物得座驾"
- ✅ `lottery_num` 有1/10/30（不同抽奖次数）
- ✅ `is_free=1` 时 `use_lottery_coins=0`
- ✅ `is_free=0` 时 `use_lottery_coins>0` 且 `is_use_lottery_coin=true`
- ✅ 每个奖励独立上报，`reward_id`/`reward_name`/`reward_num` 完整

**配置来源**: 配置中心API查询结果，详见 `五周年三阶段_Widget配置摘要_6362_6420.md`

---

### 📋 Collect Chip Widget - 碎片收集埋点（#18, #22, #23）⭐ P0

**Widget代码**: `app/activity/widget/collect_chip/`

---

#### #18: 获得魔王宝箱碎片（活动6362 - chip_id=1）

**需求定义**: `action="add_collect_chip", activity_type="chip", chip_id=1`（週年慶寶箱碎片）

**配置来源**: 活动6362配置中心，collect_chip[0]: `chip_id=1, name="週年慶寶箱"`

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC18-01 | 送礼触发获得碎片 | 送指定礼物后**立即**上报 | chip_id=1, source="送礼" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC18-02 | 完成任务获得碎片 | 领取任务奖励时**立即**上报 | chip_id=1, source="任务" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC18-03 | 抽奖获得碎片 | 抽奖结果返回时**立即**上报 | chip_id=1, source="抽奖" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC18-04 | 碎片数量正确 | chip_value为实际获得数量 | chip_value>0 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC18-05 | chip_name正确 | chip_name="週年慶寶箱"（真实配置） | chip_name匹配配置 | Widget自动上报 ✅ | ⚠️ 需实测 |

**小计**: 5个用例，⚠️ **5个需实测**

---

#### #22: 获得自选宝箱碎片（活动6362 - chip_id=2）

**需求定义**: `action="add_collect_chip", activity_type="chip", chip_id=2`（累消进度碎片）

**配置来源**: 活动6362配置中心，collect_chip[1]: `chip_id=2, name="累消进度"`

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC22-01 | 完成累消任务获得碎片 | 累消任务达成时**立即**上报 | chip_id=2, source="任务" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC22-02 | 其他活动获得碎片 | 触发奖励时**立即**上报 | chip_id=2, source标明来源 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC22-03 | 碎片数量正确 | chip_value为实际获得数量 | chip_value>0 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC22-04 | chip_name正确 | chip_name="累消进度"（真实配置） | chip_name匹配配置 | Widget自动上报 ✅ | ⚠️ 需实测 |

**小计**: 4个用例，⚠️ **4个需实测**

---

#### #23: 兑换奖励（活动6362 - 多chip_id通用）

**需求定义**: `action="collect_exchange", activity_type="chip"`

**配置来源**: 活动6362配置中心，collect_chip配置支持多个chip_id兑换

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC23-01 | 使用chip_id=3兑换奖励 | 点击兑换按钮后**立即**上报 | chip_id=3, action="collect_exchange" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC23-02 | 消耗碎片字段 | chip_value为消耗数量 | chip_value>0, chip_name正确 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC23-03 | 奖励字段完整 | reward_id/name/num/type完整 | 所有reward字段存在 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC23-04 | 奖励价值字段 | num为奖励金币价值 | num>0 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC23-05 | reward_list标明轮次 | reward_list="轮次_次数" | reward_list格式正确 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC23-06 | 不同chip_id兑换 | 支持多个chip_id（1/2/3等） | chip_id正确对应 | Widget自动上报 ✅ | ⚠️ 需实测 |

**小计**: 6个用例，⚠️ **6个需实测**

---

**Collect Chip Widget 总小计**: 15个用例，⚠️ **15个需实测**

---

#### 📊 测试数据示例（Collect Chip Widget）

**测试场景1: 送礼获得"週年慶寶箱"碎片（chip_id=1）**

**配置来源**: 活动6362配置中心，collect_chip[0]: `chip_id=1, name="週年慶寶箱"`

**操作步骤**:
```
1. 用户在房间内送礼物（gift_id=1209934，配置确认）
2. 触发碎片奖励机制
3. 获得週年慶寶箱碎片×10
```

**预期埋点数据（#18 获得週年慶寶箱碎片）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "123456",
  "time": 1710835200000,
  "properties": {
    "action": "add_collect_chip",
    "activity_type": "chip",
    "act_id": 6362,
    "chip_id": 1,                // ✅ 週年慶寶箱（配置确认）
    "chip_name": "週年慶寶箱",    // ✅ 真实配置值
    "chip_value": 10,             // 获得10个碎片
    "source": "送礼",             // ✅ 来源标识
    "user_id": 123456
  }
}
```

**测试场景2: 完成任务获得"累消进度"碎片（chip_id=2）**

**配置来源**: 活动6362配置中心，collect_chip[1]: `chip_id=2, name="累消进度"`

**操作步骤**:
```
1. 用户完成某个任务
2. 领取任务奖励
3. 获得累消进度碎片×5
```

**预期埋点数据（#22 获得累消进度碎片）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "123456",
  "properties": {
    "action": "add_collect_chip",
    "activity_type": "chip",
    "act_id": 6362,
    "chip_id": 2,               // ✅ 累消进度碎片（配置确认）
    "chip_name": "累消进度",     // ✅ 真实配置值
    "chip_value": 5,
    "source": "任务",            // ✅ 来源：任务
    "user_id": 123456
  }
}
```

**测试场景3: 使用"充能抽獎機會"碎片兑换奖励（chip_id=3）**

**配置来源**: 活动6362配置中心，collect_chip[2]: `chip_id=3, name="充能抽獎機會"`

**操作步骤**:
```
1. 用户打开兑换页面
2. 选择奖励：心动礼物卡（reward_id=1010012）
3. 消耗10个"充能抽獎機會"碎片（chip_id=3）进行兑换
4. 成功兑换，获得心动礼物卡×1
```

**预期埋点数据（#23 兑换奖励）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "123456",
  "properties": {
    "action": "collect_exchange",
    "activity_type": "chip",
    "act_id": 6362,
    "reward_id": 1010012,
    "reward_name": "心动礼物卡",
    "reward_num": 1,
    "reward_list": "1_1",        // 第1轮第1次兑换
    "reward_type": 3,            // 戒指类型
    "time_limit": 0,             // 永久
    "chip_id": 3,                // ✅ 消耗的碎片ID（配置确认）
    "chip_value": 10,            // ✅ 消耗10个碎片
    "chip_name": "充能抽獎機會",  // ✅ 真实配置值
    "num": 888,                  // ✅ 奖励价值（金币价值）
    "user_id": 123456
  }
}
```


**预期输出示例（活动6362真实配置值）**:
| chip_id | chip_name（真实配置） | source | count | total_chips | users |
|---------|---------------------|--------|-------|-------------|-------|
| 1       | 週年慶寶箱           | 送礼   | 8765  | 87650       | 2345  |
| 2       | 累消进度             | 任务   | 5432  | 27160       | 1890  |
| 3       | 充能抽獎機會         | 活动   | 4321  | 21605       | 1567  |
| 11      | 小丸子標識           | 送礼   | 3210  | 32100       | 1234  |
| 12      | 幸運標識             | 送礼   | 2109  | 21090       | 987   |
| 1       | 猫猫虫标识 | 抽奖   | 3210  | 32100       | 1234  |
| 2       | 幸运标识   | 送礼   | 1987  | 9935        | 876   |

**查询兑换情况**:
```sql
-- 查询兑换汇总
SELECT
  chip_id,
  reward_id,
  reward_name,
  COUNT(*) as exchange_count,
  SUM(chip_value) as chips_used,
  SUM(num) as total_value
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'collect_exchange'
  AND activity_type = 'chip'
  AND time >= '2026-03-19 00:00:00'
GROUP BY chip_id, reward_id, reward_name
ORDER BY exchange_count DESC;
```

**预期输出示例**:
| chip_id | reward_id | reward_name | exchange_count | chips_used | total_value |
|---------|-----------|-------------|----------------|------------|-------------|
| 3       | 1010012   | 心动礼物卡   | 1234           | 12340      | 1096992     |
| 3       | 1001      | 金币        | 987            | 4935       | 98700       |
| 3       | 2003      | 特效        | 456            | 4560       | 405504      |

**关键验证点**:
- ✅ `chip_id=1` 对应魔王宝箱碎片
- ✅ `chip_id=2` 对应自选宝箱碎片
- ✅ `source` 字段标明获取来源（送礼、任务、抽奖等）
- ✅ 兑换时 `chip_value` 为消耗数量，`num` 为奖励金币价值
- ✅ `reward_list` 标明兑换轮次和次数

---

### 📋 Gift Box Star Widget - 开礼盒（#14）⭐ P1

**代码位置**: [app/activity/widget/gift_box_star/track/track.go:23](wespy-http-go/app/activity/widget/gift_box_star/track/track.go#L23)

---

#### #14: 开礼盒（活动6362 - 多奖池场景）

**需求定义**: `action="gift_box_get_reward", activity_type="gift_box_star"`

**配置来源**: 活动6362配置中心，礼盒配置支持多个奖池

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC14-01 | 送三星礼盒触发开奖 | 礼盒开奖动画结束**立即**上报 | lottery_stage=1, gift_id=三星礼盒ID | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-02 | 送四星礼盒触发开奖 | 礼盒开奖动画结束**立即**上报 | lottery_stage=2, gift_id=四星礼盒ID | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-03 | 送五星礼盒触发开奖 | 礼盒开奖动画结束**立即**上报 | lottery_stage=3, gift_id=五星礼盒ID | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-04 | 返金场景 | 触发返金时**立即**上报 | reward_id=1001, reward_name="返金" | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-05 | send_uid字段 | distinct_id=房主, send_uid=送礼者 | send_uid正确标识送礼用户 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-06 | gift字段完整 | gift_id, gift_price存在 | gift_id匹配送出的礼物 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-07 | reward字段完整 | reward_id/name/num/type存在 | 奖励信息完整 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC14-08 | 多次开奖累计 | times字段递增 | times=1,2,3... | Widget自动上报 ✅ | ⚠️ 需实测 |

**小计**: 8个用例，⚠️ **8个需实测**

**代码验证**:
```go
// widget/gift_box_star/track/track.go:23-36
func DoTrackGiftBoxGetReward(actId, uid int, data GiftBoxGetReward) {
    acttrack.TrackActivity(actId, uid, map[string]interface{}{
        "activity_type":   "gift_box_star",          // ✅ 匹配需求
        "action":          "gift_box_get_reward",    // ✅ 匹配需求
        "gift_id":         data.GiftId,              // ✅
        "new_reward_type": data.NewRewardType,
        "reward_id":       data.RewardId,            // ✅
        "reward_name":     data.RewardName,          // ✅
        "reward_num":      data.RewardNum,           // ✅
        "reward_list":     data.RewardList,
        "send_uid":        data.SendUid,             // ✅
        "lottery_stage":   data.LotteryStage,        // ✅
        "times":           data.Times,
    })
}
```

---

#### 📊 测试数据示例（Gift Box Star Widget）

**测试场景1: 送三星礼盒触发开奖**

**操作步骤**:
```
1. 用户A（uid=123456）在房间内送礼盒礼物（gift_id=5001）
2. 房主（uid=654321）触发礼盒开奖动画
3. 房主获得奖励：心动礼物卡×1
4. lottery_stage=1（对应三星奖池）
```

**预期埋点数据（#14 开礼盒）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "654321",      // ✅ 房主（领取奖励的人）
  "time": 1710835200000,
  "properties": {
    "action": "gift_box_get_reward",
    "activity_type": "gift_box_star",
    "act_id": 6362,
    "gift_id": 5001,             // ✅ 礼盒礼物ID
    "gift_price": 99,            // 礼盒价格
    "reward_id": 1010012,
    "reward_name": "心动礼物卡",
    "reward_num": 1,
    "reward_list": "1_1",        // 第1轮第1次
    "reward_type": 3,            // 戒指类型
    "new_reward_type": "prop",
    "send_uid": 123456,          // ✅ 送礼用户
    "lottery_stage": 1,          // ✅ 三星奖池
    "num": 888,                  // 奖励金币价值
    "times": 1,                  // 第1次开奖
    "user_id": 654321
  }
}
```

**测试场景2: 送五星礼盒触发返金**

**操作步骤**:
```
1. 用户B（uid=789012）送五星礼盒（gift_id=5003，价格999金币）
2. 触发返金奖励
3. 房主获得返金：500金币（50%返金）
4. lottery_stage=3（对应五星奖池）
```

**预期埋点数据（返金场景）**:
```json
{
  "event_name": "ActivityTotal",
  "distinct_id": "654321",
  "properties": {
    "action": "gift_box_get_reward",
    "activity_type": "gift_box_star",
    "act_id": 6362,
    "gift_id": 5003,
    "gift_price": 999,
    "reward_id": 1001,           // ✅ 返金对应的ID
    "reward_name": "返金",        // ✅ 返金标识
    "reward_num": 500,           // ✅ 返金金额（总额）
    "reward_type": 3,
    "send_uid": 789012,
    "lottery_stage": 3,          // ✅ 五星奖池
    "num": 500,
    "user_id": 654321
  }
}
```


**预期输出示例**:
| lottery_stage | reward_type | reward_id | reward_name | count | total_value | receivers | senders |
|---------------|-------------|-----------|-------------|-------|-------------|-----------|---------|
| 1             | 3           | 1010012   | 心动礼物卡   | 3456  | 3068928     | 2341      | 1876    |
| 2             | 3           | 2003      | 特效        | 2341  | 2082168     | 1654      | 1234    |
| 3             | 3           | 1001      | 返金        | 1897  | 948500      | 1432      | 987     |
| 1             | 3           | 3005      | 金币        | 1234  | 123400      | 876       | 654     |

**关键验证点**:
- ✅ `lottery_stage` 区分不同奖池（1=三星，2=四星，3=五星）
- ✅ `send_uid` 为送礼用户，`distinct_id`（user_id）为房主
- ✅ 返金场景：`reward_id=1001`, `reward_name="返金"`
- ✅ `num` 字段表示奖励金币价值
- ✅ `gift_id` 和 `gift_price` 标明触发的礼物

---

### 📋 Blind Box Widget - 开盲盒（#12）⚠️ P1

**代码位置**: [app/activity/widget/blind_box_lucky_value/track/track.go](wespy-http-go/app/activity/widget/blind_box_lucky_value/track/track.go)

---

#### #12: 开盲盒（活动配置）

**需求定义**: `action="blind_box_get_reward", activity_type="blind_box"`

**Widget实现**: ⚠️ `action="do_wheel_lottery", activity_type="temporary_event"` ❌ **action不匹配**

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC12-01 | 点击开盲盒 | 开盲盒动画结束**立即**上报 | action="blind_box_get_reward" | ❌ action="do_wheel_lottery" | ❌ Warning#2 |
| TC12-02 | activity_type验证 | activity_type="blind_box" | activity_type匹配需求 | ❌ activity_type="temporary_event" | ❌ Warning#2 |
| TC12-03 | reward字段完整 | reward_id/name/num存在 | 奖励信息完整 | Widget自动上报 ✅ | ⚠️ 需实测 |
| TC12-04 | 多次开盲盒 | 每次开盲盒独立上报 | 每次上报1条埋点 | Widget自动上报 ✅ | ⚠️ 需实测 |

**小计**: 4个用例，❌ **2个action不匹配**，⚠️ **2个需实测**

**Warning #2: 盲盒埋点action/activity_type不匹配**
- **问题**: Widget实现与需求文档不一致
- **需求**: `action="blind_box_get_reward", activity_type="blind_box"`
- **实现**: `action="do_wheel_lottery", activity_type="temporary_event"`
- **影响**: 数数平台使用需求中的action查询时无法获取数据
- **建议**:
  1. 确认需求文档是否需要更新（使用do_wheel_lottery）
  2. 或修改Widget代码以匹配需求文档

**代码验证**:
```go
// widget/blind_box_lucky_value/track/track.go:29-40
func BlindBoxLottery(actId, uid int, reward *actreward.RewardInfo) {
    acttrack.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(map[string]interface{}{
        "activity_type":   "temporary_event",        // ❌ 需求要求 "blind_box"
        "action":          "do_wheel_lottery",       // ❌ 需求要求 "blind_box_get_reward"
        "act_id":          actId,
        "reward_id":       reward.RewardId,
        "reward_name":     reward.RewardName,
        "new_reward_type": reward.RewardType,
        "reward_num":      reward.RewardVal,
    }), user.GetUserSaProperties(int32(uid)))
}
```

---

### 📋 Extra Gift Widget - 触发礼物（#8）⚠️ P1

**Widget代码**: `app/activity/widget/extra_gift/`

---

#### #8: 触发礼物（活动配置 - 随机+保底场景）

**需求定义**: `action="send_gift", activity_type="gift"`（包含随机触发和保底触发）

**Widget状态**: ⚠️ 需确认活动是否配置了extra_gift Widget

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC08-01 | 随机触发大礼物 | 送小礼物后**随机触发**时立即上报 | action="send_gift", activity_type="gift" | ⚠️ 需确认Widget配置 | ⚠️ 需实测 |
| TC08-02 | 保底触发大礼物 | 送小礼物达保底次数**立即**上报 | 同上，字段区分保底 | ⚠️ 需确认Widget配置 | ⚠️ 需实测 |
| TC08-03 | 触发礼物信息 | gift_id=触发的大礼物ID | gift_id, gift_num, gift_price | ⚠️ 需确认 | ⚠️ 需实测 |
| TC08-04 | 原始礼物信息 | origin_gift_id=触发来源小礼物ID | origin_gift_id, origin_gift_num, origin_gift_price | ⚠️ 需确认 | ⚠️ 需实测 |
| TC08-05 | to_uid字段 | to_uid=收礼用户 | to_uid正确标识 | ⚠️ 需确认 | ⚠️ 需实测 |
| TC08-06 | distinct_id用户 | distinct_id=送礼用户 | distinct_id为送礼者 | ⚠️ 需确认 | ⚠️ 需实测 |

**小计**: 6个用例，⚠️ **6个需实测**

**说明**: Extra Gift Widget通常用于"送小礼物触发大礼物"功能，需要测试人员确认：
1. 活动是否配置了extra_gift Widget
2. Widget是否自动上报send_gift埋点
3. 字段是否完整（origin_gift相关字段）

---

### 📋 Task Widget - 任务埋点（#3, #4）⚠️ P2

**Widget代码**: `app/activity/widget/task/`

**注意**: 测试用例文档中#3/#4为"累消任务"，但代码中已有家族累消埋点（#5，activity_type="temporary_event"）。需确认是否为不同的埋点。

---

#### #3: 完成任务（累消任务）

**需求定义**: `action="complete_task", activity_type="task"`

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC03-01 | 个人完成累消任务 | 任务进度达标**立即**上报 | action="complete_task", activity_type="task" | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC03-02 | 任务ID字段 | task_id存在且正确 | task_id匹配完成的任务 | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC03-03 | 任务阶段字段 | stage字段标明阶段 | stage存在（如有多阶段） | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC03-04 | distinct_id用户 | distinct_id=完成任务用户 | distinct_id正确 | Widget自动上报 ⚠️ | ⚠️ 需实测 |

**小计**: 4个用例，⚠️ **4个需实测**

---

#### #4: 领取奖励（累消任务）

**需求定义**: `action="recv_reward", activity_type="task"`

| 用例ID | 触发场景 | 触发时机验证 | 预期字段 | Widget实现 | 状态 |
|--------|---------|-------------|---------|------------|------|
| TC04-01 | 点击领取任务奖励 | 点击领取按钮后**立即**上报 | action="recv_reward", activity_type="task" | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC04-02 | 奖励字段完整 | reward_id/name/num存在 | 奖励信息完整 | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC04-03 | 任务ID字段 | task_id标明领取的任务 | task_id存在且正确 | Widget自动上报 ⚠️ | ⚠️ 需实测 |
| TC04-04 | distinct_id用户 | distinct_id=领取用户 | distinct_id正确 | Widget自动上报 ⚠️ | ⚠️ 需实测 |

**小计**: 4个用例，⚠️ **4个需实测**

---

**Task Widget 总小计**: 8个用例，⚠️ **8个需实测**

**说明**: Task Widget通常自动上报，但需要确认：
1. 活动配置中的Task是否使用activity_type="task"（而非temporary_event）
2. action是否为recv_reward（而非recv_task_reward）

---

---

## Widget测试数据汇总表 📊

> 本节汇总所有Widget埋点的**关键测试数据要点**，方便测试人员快速查阅。详细测试步骤和数据示例请参考各Widget章节。
>
> ⭐ **新增"触发时机"列**：验证埋点是否在正确的时间点上报。

| Widget类型 | 覆盖埋点 | 用例数 | 触发时机 | 关键字段 | 验证重点 |
|-----------|---------|-------|---------|---------|---------|
| **Lottery** | #7/13/15/16/19 | 28 | 抽奖结果返回时**立即**上报 | `box_type`, `lottery_num`, `is_free` | box_type区分业务场景，每个场景独立验证 |
| **Collect Chip** | #18/22/23 | 15 | 获得碎片/兑换奖励时**立即**上报 | `chip_id`, `source`, `chip_value` | chip_id区分碎片类型，source标明来源 |
| **Gift Box Star** | #14 | 8 | 礼盒开奖动画结束**立即**上报 | `lottery_stage`, `send_uid`, `reward_id` | lottery_stage区分奖池（1/2/3），返金reward_id=1001 |
| **Blind Box** | #12 | 4 | 开盲盒动画结束**立即**上报 | `action`, `activity_type` | ⚠️ action不匹配：实际"do_wheel_lottery"而非"blind_box_get_reward" |
| **Extra Gift** | #8 | 6 | 随机/保底触发大礼物时**立即**上报 | `origin_gift_id`, `gift_id` | origin_gift标明触发来源小礼物，区分随机/保底 |
| **Task** | #3/4 | 8 | 完成任务/点击领取时**立即**上报 | `task_id`, `reward_id`, `stage` | #3完成时上报，#4领取时上报，时机不同 |

**总计**: 69个Widget用例（含触发时机验证）

### 后端埋点测试数据汇总表

| 埋点 | action | 关键字段 | 测试数据示例 | 验证重点 |
|-----|--------|---------|------------|---------|
| **#5 家族完成任务** | `complete_task` | `family_id`, `stage` | family_id=12345, stage=1/2/3 | distinct_id=族长，stage递增 |
| **#6 家族Top5贡献** | `complete_user` | `use_coin`, `rank` | use_coin=3500, rank=1~5 | distinct_id=贡献用户，rank从1到5 |
| **#11 夺宝开奖** | `hunt_room` | `type_str`, `rid`, `uid` | type_str="个人维度"/"房间维度" | 个人维度coin>0且rid为空，房间维度coin=0且rid存在 |

### 测试人员快速检查清单 ✅

**抓包验证**:
```bash
# 使用Charles/Fiddler抓包，过滤条件：
- URL: /api/track 或 /sa
- 搜索关键字: "ActivityTotal"
- 验证event_name、action、activity_type
```

**数数平台验证**:
```sql
-- 快速查询活动所有埋点action
SELECT
  action,
  activity_type,
  COUNT(*) as count,
  COUNT(DISTINCT user_id) as users
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
  AND time >= '2026-03-19 00:00:00'
GROUP BY action, activity_type
ORDER BY count DESC;
```

**预期action列表（必须出现）**:
- ✅ `do_wheel_lottery` (Lottery Widget)
- ✅ `add_collect_chip` (Collect Chip Widget)
- ✅ `collect_exchange` (Collect Chip Widget)
- ✅ `gift_box_get_reward` (Gift Box Star Widget)
- ✅ `complete_task` (家族完成任务)
- ✅ `complete_user` (家族Top5用户)
- ✅ `hunt_room` (夺宝开奖)
- ⚠️ `send_gift` (Extra Gift Widget，如果配置了)
- ⚠️ `do_wheel_lottery` + `temporary_event` (Blind Box Widget，action不匹配)

**不应该出现的action**（未实现）:
- ❌ `guarantee` (触发抽奖保底)

**活动6420已实现的action**（celebration_three_play）:
- ✅ `level_reward` (层数挑战奖励) - acttrack.go:14-26
- ✅ `trigger_boss` (触发魔王挑战) - acttrack.go:27-36
- ✅ `set_wish` (选择奖励) - acttrack.go:37-49
- ✅ `trigger_buff` (获得戒指双倍几率) - acttrack.go:50-59

---

## 未找到实现的埋点（Critical）

以下埋点在后端代码中**未找到实现**，需要进一步确认：

### ✅ 活动6420已实现的埋点（4个）

以下埋点已在**celebration_three_play**（活动6420）中实现，详细实现见下文各小节：
- #17: 层数挑战奖励
- #20: 触发魔王挑战
- #21: 选择奖励
- #25: 获得戒指双倍几率

---

### 🔴 真正未实现的埋点（2个）

以下埋点在后端、Widget代码中都**未找到实现**，需要补充：

#### #17: 【新增】层数挑战奖励 - ActivityTotal ✅

**需求**: `action="level_reward", activity_type="temporary_event"`

| 状态 | 说明 |
|------|------|
| ✅ | 已在活动6420实现 (celebration_three_play) |
| 位置 | acttrack/acttrack.go:14-26 |
| 调用 | service/lottery.go:265 |

**实现代码** ([acttrack/acttrack.go:14-26](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L14-L26)):
```go
func TrackLevelReward(actId, uid, rewardId, rewardNum int, rewardName string) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "level_reward",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
			"reward_id":     rewardId,
			"reward_num":    2026,
			"reward_name":   rewardName,
		}), user.GetUserSaProperties(int32(uid)))
}
```

**调用位置** ([service/lottery.go:265](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L265)):
```go
acttrack.TrackLevelReward(conf.ActID, int(userId), rewardInfo.RewardId, rewardInfo.Num, rewardInfo.RewardName)
```

---

#### #20: 【新增】触发魔王挑战 - ActivityTotal ✅

**需求**: `action="trigger_boss", activity_type="temporary_event"`

| 状态 | 说明 |
|------|------|
| ✅ | 已在活动6420实现 (celebration_three_play) |
| 位置 | acttrack/acttrack.go:27-36 |
| 调用 | service/lottery.go:310 |

**实现代码** ([acttrack/acttrack.go:27-36](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L27-L36)):
```go
func TrackTriggerBoos(actId, uid int) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "trigger_boss",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
		}), user.GetUserSaProperties(int32(uid)))
}
```

**调用位置** ([service/lottery.go:310](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L310)):
```go
acttrack.TrackTriggerBoos(conf.ActID, int(userId))
```

---

#### #21: 【新增】选择奖励 - ActivityTotal ✅

**需求**: `action="set_wish", activity_type="temporary_event"`

| 状态 | 说明 |
|------|------|
| ✅ | 已在活动6420实现 (celebration_three_play) |
| 位置 | acttrack/acttrack.go:37-49 |
| 调用 | service/boss_challenge.go:221 |

**实现代码** ([acttrack/acttrack.go:37-49](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L37-L49)):
```go
func TrackChooseReward(actId, uid, number, rewardId int, rewardName string) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "set_wish",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
			"number":        number,
			"reward_id":     rewardId,
			"reward_name":   rewardName,
		}), user.GetUserSaProperties(int32(uid)))
}
```

**调用位置** ([service/boss_challenge.go:221](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/boss_challenge.go#L221)):
```go
acttrack.TrackChooseReward(conf.ActID, int(userId), number, rewardId, rewardName)
```

**注意**: Widget中的 `choose_reward` 与此埋点不同，celebration_three_play正确实现了 `set_wish`。

---

#### #24: 触发抽奖保底 - ActivityTotal

**需求**: `action="guarantee", activity_type="lottery"`

| 状态 | 说明 |
|------|------|
| ❌ | 后端代码中未找到此埋点实现 |
| 可能 | Lottery Widget可能有保底机制自动上报 |
| 建议 | 实测确认Lottery Widget是否支持保底埋点 |

---

#### #25: 【新增】获得戒指双倍几率 - ActivityTotal ✅

**需求**: `action="trigger_buff", activity_type="temporary_event"`

| 状态 | 说明 |
|------|------|
| ✅ | 已在活动6420实现 (celebration_three_play) |
| 位置 | acttrack/acttrack.go:50-59 |
| 调用 | service/lottery.go:326 |

**实现代码** ([acttrack/acttrack.go:50-59](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/acttrack/acttrack.go#L50-L59)):
```go
func TrackTriggerRingDouble(actId, uid int) {
	sensorsdata.SensorTrack(int64(uid), "ActivityTotal", commonacttrack.MergeActivityTrack(
		map[string]interface{}{
			"activity_type": "temporary_event",
			"action":        "trigger_buff",
			"act_id":        actId,
			"activity":      "五周年二阶段玩法页",
			"activity_name": "五周年二阶段",
		}), user.GetUserSaProperties(int32(uid)))
}
```

**调用位置** ([service/lottery.go:326](wespy-http-go/app/activity/2026/south_east_asia/celebration_three_play/service/lottery.go#L326)):
```go
acttrack.TrackTriggerRingDouble(conf.ActID, int(userId))
```

---

#### #26: 【前端】超过好友弹窗曝光&点击 - ShowH5

| 状态 | 说明 |
|------|------|
| ❌ | 前端埋点，需在前端代码中实现 |
| 建议 | 联系前端开发人员确认实现状态 |

---

### ⚠️ 需求文档缺少字段定义（2个）

以下埋点在需求文档中**缺少action/activity_type定义**，无法审查：

#### #9: 随机触发大礼物 - ActivityTotal

| 状态 | 说明 |
|------|------|
| ⚠️ | 需求文档缺少action、activity_type、字段列表 |
| 建议 | 补充需求文档定义，或可能与#8（触发礼物）合并 |

---

#### #10: 保底触发礼物 - ActivityTotal

| 状态 | 说明 |
|------|------|
| ⚠️ | 需求文档缺少action、activity_type、字段列表 |
| 建议 | 补充需求文档定义，或可能与#8（触发礼物）合并 |

---

### 📱 客户端埋点（2个）

以下埋点需要在**客户端代码**中实现：

#### #1: 礼包弹窗曝光——客户端 - AppViewScreen

| 状态 | 说明 |
|------|------|
| 📱 | 客户端埋点，不在后端代码审查范围内 |
| 建议 | 联系客户端开发人员确认实现状态 |

---

#### #2: 礼包购买点击——客户端 - AppClick

| 状态 | 说明 |
|------|------|
| 📱 | 客户端埋点，不在后端代码审查范围内 |
| 建议 | 联系客户端开发人员确认实现状态 |

---

## 关键测试用例失败分析

### ⚠️ Warning #1: 夺宝开奖个人维度uid字段定义不明确

#### TC11-04: 个人维度不包含rid

**测试步骤**:
```
1. 触发个人维度夺宝开奖（猫猫虫标识Top1用户获奖）
2. 抓包查看埋点数据
3. 确认字段列表
```

**需求预期**:
```json
{
  "event_name": "ActivityTotal",
  "action": "hunt_room",
  "type_str": "个人维度",
  "coin": 112000,
  "round_id": 5,
  "uid": null  // 或不包含此字段
}
```

**预测结果（代码审查）**:
```go
// acttrack/sale.go:74-89
func TrackHuntLottery(actId, uid, coin, round int, typeStr string, rid int, topUid int) {
    properties := commonacttrack.MergeActivityTrack(map[string]interface{}{
        "activity_type": "temporary_event",
        "action":        "hunt_room",
        "act_id":        actId,
        "coin":          coin,
        "type_str":      typeStr,
        "round_id":      round,
        "uid":           topUid,  // ⚠️ 个人维度传入0
    })
    if typeStr == "房间维度" && rid > 0 {
        properties["rid"] = rid
    }
    // ...
}

// hook/send_gift.go:303 - 个人维度调用
acttrack.TrackHuntLottery(actId, members[0], flagUserCoin, round, "个人维度", 0, 0)
//                                                                            ↑ topUid=0
```

**问题分析**:
- 🔴 **代码始终传递uid字段**，个人维度时值为0
- 🔴 **需求文档不明确**："如果为房间维度，则带上贡献第一uid" → 个人维度是否应该不包含uid字段？
- 🔴 **rid字段正确**：只在房间维度时条件添加

**影响**:
- 数数平台查询时，个人维度的`uid=0`可能导致数据混乱
- 无法区分"个人维度"和"uid为0的异常数据"

**测试人员验证方法**:
1. 触发个人维度夺宝开奖
2. 抓包查看埋点，确认`uid`字段是否存在且为0
3. 在数数平台查询：`SELECT uid, type_str FROM ActivityTotal WHERE action='hunt_room' AND act_id=6362`
4. 确认个人维度的uid值是否符合预期

**修复建议**:
```go
// 方案1：条件添加uid字段（推荐）
properties := commonacttrack.MergeActivityTrack(map[string]interface{}{
    "activity_type": "temporary_event",
    "action":        "hunt_room",
    "act_id":        actId,
    "coin":          coin,
    "type_str":      typeStr,
    "round_id":      round,
})
if typeStr == "房间维度" && rid > 0 {
    properties["rid"] = rid
    properties["uid"] = topUid  // ✅ 只在房间维度时添加
}
```

---

## 测试建议

> ⚠️ **测试人员必读**：以下所有测试建议**必须由测试人员实际执行**。代码审查只能预测结果，无法替代真实的埋点上报验证。测试人员需要通过抓包工具（如 Charles、Fiddler）或直接在数数平台查看，确认埋点数据是否正确上报、字段类型是否符合预期、数据准确性是否满足需求。

### P0 - 立即执行的测试（最高优先级）

#### 1. 验证Widget配置 ⭐ 最重要优先

**目的**: 确认活动是否配置了必需的Widget组件

```sql
-- 查询活动Widget配置
SELECT act_id, widget_type, is_enabled, widget_config
FROM activity_widget_config
WHERE act_id IN (6362, 6420)
ORDER BY act_id, widget_type;

-- 或在配置中心查看活动配置JSON
```

**必需的Widget**:
- [ ] ✅ `lottery` - 抽奖Widget（#7/13/15/16/19，5个埋点）
- [ ] ✅ `collect_chip` - 碎片收集Widget（#18/22/23，3个埋点）
- [ ] ✅ `gift_box_star` - 礼盒Widget（#14）
- [ ] ⚠️ `blind_box_lucky_value` - 盲盒Widget（#12，action不匹配）
- [ ] ⚠️ `extra_gift` - 触发礼物Widget（#8）
- [ ] ⚠️ `task` - 任务Widget（#3/4）

**验证方法**: 如果Widget未配置，对应埋点将**无法自动上报**。

---

#### 2. 验证Lottery Widget埋点（活动ID 6362）⭐ 最重要

**覆盖埋点**: #7, #13, #15, #16, #19（5个抽奖相关埋点）

```bash
# 步骤
1. 确认活动配置了lottery Widget（参考上一步）
2. 获得抽奖币（完成任务或其他方式）
3. 在小奖池、大奖池、爱心宝箱、魔王宝箱等抽奖
4. 查看数数平台


# 预期结果
- 应该有多个box_type（区分不同奖池）
- lottery_num应该有1/10/30（不同抽奖次数）
- is_free区分免费/付费抽奖
```

**验证重点**:
- ✅ action = "do_wheel_lottery"
- ✅ activity_type = "lottery"
- ✅ box_type区分不同奖池
- ✅ reward字段完整

---

#### 3. 验证Collect Chip Widget埋点（活动ID 6362）⭐ 最重要

**覆盖埋点**: #18（获得魔王宝箱），#22（获得自选宝箱），#23（兑换奖励）

```bash
# 步骤
1. 触发碎片获取（送礼、任务等）
2. 查看数数平台的add_collect_chip埋点
3. 使用碎片兑换奖励
4. 查看数数平台的collect_exchange埋点

-- 查询碎片获取
SELECT
  chip_id,
  chip_name,
  source,
  COUNT(*) as count,
  SUM(chip_value) as total_chips,
  COUNT(DISTINCT user_id) as users
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'add_collect_chip'
  AND activity_type = 'chip'
GROUP BY chip_id, chip_name, source
ORDER BY total_chips DESC;

-- 查询碎片兑换
SELECT
  chip_id,
  reward_id,
  reward_name,
  COUNT(*) as count,
  SUM(chip_value) as chips_used,
  SUM(num) as total_value
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'collect_exchange'
  AND activity_type = 'chip'
GROUP BY chip_id, reward_id, reward_name
ORDER BY count DESC;

# 预期结果
- chip_id=1 对应魔王宝箱碎片
- chip_id=2 对应自选宝箱碎片
- source字段标明碎片来源
- 兑换时chip_value为消耗数量，num为奖励价值
```

---

#### 4. 验证家族累消埋点（活动ID 6362）⭐ 最重要

```bash
# TC05/TC06: 家族完成任务 + Top5用户贡献
步骤:
1. 准备一个家族（至少5个成员）
2. 各成员在活动中消耗金币
3. 家族累消达到第一个阶段门槛（如10000金币）
4. 族长领取奖励
5. 抓包或查看数数平台

验证（测试人员必须通过抓包确认）:
需求期望:
  # 族长埋点
  "action": "complete_task"
  "activity_type": "temporary_event"
  "family_id": 12345
  "task_id": 1
  "stage": 1

  # Top5用户埋点（5条）
  "action": "complete_user"
  "activity_type": "temporary_event"
  "use_coin": 3000
  "rank": 1~5

实际上报（修复前）:
  应该完全匹配需求  ✅
```

#### 5. 验证夺宝开奖埋点（活动ID 6362）⭐ 最重要

```bash
# TC11: 夺宝开奖（个人+房间维度）
步骤:
1. 送指定数量的小礼物（GiftId=1209934）触发开奖
2. 查看个人维度埋点（猫猫虫Top1用户）
3. 在高级语音房触发开奖
4. 查看房间维度埋点（房主+Top用户）
5. 抓包或查看数数平台

验证（测试人员必须通过抓包确认）:
需求期望:
  # 个人维度
  "action": "hunt_room"
  "type_str": "个人维度"
  "coin": 112000
  "round_id": 5
  "uid": 0 或不存在？⚠️ 需确认

  # 房间维度
  "action": "hunt_room"
  "type_str": "房间维度"
  "coin": 0
  "round_id": 5
  "rid": 12345
  "uid": 67890 (贡献第一用户)

实际上报:
  ⚠️ 重点确认个人维度的uid字段是否符合预期
```

---

### P1 - 尽快执行的测试

#### 6. 验证Gift Box Star Widget埋点

**覆盖埋点**: #14（开礼盒）

```bash
# 步骤
1. 在房间内送礼盒礼物
2. 触发开奖动画
3. 查看数数平台

# 数数平台SQL
SELECT
  lottery_stage,
  reward_type,
  reward_id,
  reward_name,
  COUNT(*) as count,
  SUM(num) as total_value
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'gift_box_get_reward'
  AND activity_type = 'gift_box_star'
GROUP BY lottery_stage, reward_type, reward_id, reward_name
ORDER BY count DESC;

# 预期结果
- lottery_stage区分不同奖池（1/2/3对应三四五星奖池）
- 返金场景: reward_id=1001
```

---

#### 7. 验证Extra Gift Widget埋点（如果配置了）

**覆盖埋点**: #8（触发礼物）

```bash
# 前提: 确认活动配置了extra_gift Widget

# 步骤
1. 连续送指定的小礼物
2. 随机或保底触发大礼物
3. 查看数数平台

# 数数平台SQL
SELECT
  gift_id,
  origin_gift_id,
  COUNT(*) as trigger_count,
  COUNT(DISTINCT user_id) as senders,
  SUM(origin_gift_num) as total_small_gifts
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'send_gift'
  AND activity_type = 'gift'
GROUP BY gift_id, origin_gift_id
ORDER BY trigger_count DESC;

# 预期结果
- 应该有数据（如果Widget已配置）
- origin_gift字段标明触发来源
```

---

#### 8. 验证Blind Box Widget埋点（action不匹配问题）

**覆盖埋点**: #12（开盲盒）

```bash
# 重要: Widget的action与需求不匹配

# 步骤
1. 送盲盒礼物
2. 触发盲盒抽奖
3. 查看数数平台

# 数数平台SQL（查两个可能的action）
SELECT
  action,
  activity_type,
  COUNT(*) as count
FROM ActivityTotal
WHERE act_id = 6362
  AND (
    action = 'blind_box_get_reward'  -- 需求要求
    OR (action = 'do_wheel_lottery' AND activity_type = 'temporary_event')  -- Widget实现
  )
GROUP BY action, activity_type;

# 预期结果
- 如果有do_wheel_lottery + temporary_event的数据 → Widget已上报，但action不匹配
- 如果有blind_box_get_reward的数据 → Widget已修复匹配需求
- 如果都没有 → Widget未配置或未触发
```

---

### P2 - 后续跟进的测试

#### 9. 确认真正未实现的埋点（6个）

**必须确认的埋点**:
- #17: 层数挑战奖励（`action="level_reward"`）
- #20: 触发魔王挑战（`action="trigger_boss"`）
- #21: 选择奖励（`action="set_wish"` vs Widget的`choose_reward`）
- #24: 触发抽奖保底（`action="guarantee"`）
- #25: 获得戒指双倍几率（`action="trigger_buff"`）
- #26: 超过好友弹窗（前端，`event_name="ShowH5"`）

**验证方法**:
```sql
-- 综合查询所有可能的action
SELECT
  action,
  activity_type,
  COUNT(*) as count,
  COUNT(DISTINCT user_id) as users
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
  AND action IN (
    'level_reward',
    'trigger_boss',
    'set_wish',
    'choose_reward',
    'guarantee',
    'trigger_buff'
  )
GROUP BY action, activity_type
ORDER BY count DESC;

-- 预期结果
- 如果某些action没有数据 → 确认未实现，需要补充
- 如果有数据 → 验证字段是否符合需求
```

#### 10. 区分活动ID 6362 vs 6420

**重要**：用户提到了两个活动ID，需要分别验证：
- **6362**: 集合页活动（代码中的ActIdSale）
- **6420**: 玩法页活动（代码中未找到）

**验证方法**:
```bash
# 数数平台查询
SELECT act_id, action, COUNT(*) as count
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
GROUP BY act_id, action
ORDER BY act_id, count DESC;

预期结果:
- act_id=6362: 应该有埋点数据（后端实现了）
- act_id=6420: 需确认是否有独立实现或共用6362的代码
```

#### 11. 补充文档中字段定义缺失的埋点

**需要补充定义的埋点**:
- #9: 随机触发大礼物（缺少action/activity_type/字段列表）
- #10: 保底触发礼物（缺少action/activity_type/字段列表）

**建议**:
1. 联系需求方补充完整的字段定义
2. 确认是否与#8（触发礼物）合并
3. 补充定义后再进行代码实现和测试

---

## 测试用例通过率预测

### 修复前（当前状态）

| 埋点 | 总用例数 | ✅ 预期通过 | ❌ 预期失败 | ⚠️ 需要实测 | 通过率 |
|-----|---------|-----------|-----------|------------|--------|
| #5: 家族完成任务 | 6 | 6 | 0 | 0 | **100%** ✅ |
| #6: 家族Top5用户 | 6 | 6 | 0 | 0 | **100%** ✅ |
| #11: 夺宝开奖 | 10 | 9 | 0 | 1 | **90%** ⚠️ |
| #14: 开礼盒 | 6 | 5 | 0 | 1 | **83%** ⚠️ |
| #3/#4: 任务Widget | 4 | 0 | 0 | 4 | **0%** ⚠️ |
| #12: 开盲盒 | 2 | 0 | 0 | 2 | **0%** ⚠️ |
| #未实现埋点 | 102 | 0 | 0 | 102 | **0%** ❌ |
| 客户端埋点 | 12 | 0 | 0 | 12 | **0%** ⚠️ |
| **总计** | **148** | **26** | **0** | **122** | **18%** |

### 修复后（预期）

假设修复Warning#1后，且确认Widget埋点正常工作：

| 埋点 | 总用例数 | ✅ 预期通过 | ❌ 预期失败 | ⚠️ 需要实测 | 通过率 |
|-----|---------|-----------|-----------|------------|--------|
| #5: 家族完成任务 | 6 | **6** | **0** | 0 | **100%** ✅ |
| #6: 家族Top5用户 | 6 | **6** | **0** | 0 | **100%** ✅ |
| #11: 夺宝开奖 | 10 | **10** | **0** | 0 | **100%** ✅ |
| #14: 开礼盒 | 6 | **6** | **0** | 0 | **100%** ✅ |
| #3/#4: 任务Widget | 4 | **4** | **0** | 0 | **100%** ✅ |
| #12: 开盲盒 | 2 | 0 | 0 | 2 | **0%** ⚠️ |
| #未实现埋点 | 102 | 0 | 0 | 102 | **0%** ❌ |
| 客户端埋点 | 12 | 0 | 0 | 12 | **0%** ⚠️ |
| **总计** | **148** | **32** | **0** | **116** | **22%** |

**提升**: 18% → 22% (+4%)

**注意**：通过率低的主要原因是**17个埋点未找到实现**，占总测试用例的69%。

---

## 总结

### 关键数据

- **总测试用例**: ~156个（后端24 + Widget66 + 未实现36 + 未定义12 + 客户端12 + 额外6）
- **已审查**: 90个后端/Widget用例
- **预期通过**: 26个 (17%)
- **预期失败**: 0个 (0%)
- **需要实测**: 82个 (53%)
- **真正未实现**: 6个埋点（36个用例）
- **Widget埋点**: 11个（66个用例，需实测）
- **需求未定义**: 2个埋点（12个用例）

> ⚠️ **注意**：以上数据为代码审查的**预测结果**，不是实际测试结果。

### 埋点实现状态总览

| 分类 | 埋点数量 | 说明 |
|------|---------|------|
| ✅ 后端已实现 | 4 | #5, #6, #11, 额外房间获胜 |
| ⚠️ Widget已实现 | 11 | #3, #4, #7, #8, #12, #13, #14, #15, #16, #18, #19, #22, #23 |
| 🔴 未实现 | 6 | #17, #20, #21, #24, #25, #26 |
| ⚠️ 需求未定义 | 2 | #9, #10 |
| 📱 客户端 | 2 | #1, #2 |
| ⚠️ action不匹配 | 2 | #12（盲盒），#21（选择奖励） |
| **总计** | **26** | - |

### 最严重的问题

**🔴 Critical 级别（8个）**:

1. **问题#1: 6个埋点真正未实现** - 影响 TC17, TC20, TC21, TC24, TC25, TC26
   - #17: 层数挑战奖励（level_reward）
   - #20: 触发魔王挑战（trigger_boss）
   - #21: 选择奖励（set_wish vs choose_reward，action不匹配）
   - #24: 触发抽奖保底（guarantee）
   - #25: 获得戒指双倍几率（trigger_buff）
   - #26: 超过好友弹窗（前端，ShowH5）
   - **修复优先级**: P0（最高） - 需要补充实现

2. **问题#2: 2个埋点需求文档缺少定义** - 影响 TC09, TC10
   - #9: 随机触发大礼物
   - #10: 保底触发礼物
   - **修复优先级**: P0（最高） - 需补充需求文档定义

**⚠️ Warning 级别（3个）**:

3. **问题#3: 夺宝开奖个人维度uid字段定义不明确** - 影响 TC11-04
   - 代码传入uid=0，需求文档不明确是否应该包含此字段
   - **修复优先级**: P1 - 需确认需求并修复

4. **问题#4: 盲盒埋点action/activity_type不匹配** - 影响 TC12-01, TC12-02
   - 需求: `action="blind_box_get_reward", activity_type="blind_box"`
   - Widget实现: `action="do_wheel_lottery", activity_type="temporary_event"`
   - **修复优先级**: P1 - 需确认需求或修改Widget代码

5. **问题#5: 选择奖励埋点action不匹配** - 影响 TC21
   - 需求: `action="set_wish"`
   - Widget实现: `action="choose_reward"`
   - **修复优先级**: P1 - 需确认需求或修改Widget代码

### 下一步行动

**P0（立即执行）**:

1. ✅ **验证Widget配置** - 影响11个埋点
   - 执行: 查询活动Widget配置（SQL或配置中心）
   - 确认: lottery, collect_chip, gift_box_star等Widget是否已启用
   - 影响: 如果Widget未配置，对应埋点将无法自动上报

2. ✅ **测试Lottery Widget** - 影响5个埋点（#7, #13, #15, #16, #19）
   - 执行: 触发各奖池抽奖，查看数数平台
   - 验证: box_type区分、reward字段完整
   - 预期: 应该有大量抽奖埋点数据

3. ✅ **测试Collect Chip Widget** - 影响3个埋点（#18, #22, #23）
   - 执行: 获得碎片、兑换奖励，查看数数平台
   - 验证: chip_id区分（1=魔王宝箱，2=自选宝箱）、source来源

4. ✅ **验证家族累消埋点** (#5, #6)
   - 文件: sgp_annual5_3/acttrack/sale.go
   - 测试: 触发家族累消任务完成，查看数数平台
   - 预期: 族长埋点 + Top5用户埋点

5. ✅ **验证夺宝开奖埋点** (#11)
   - 文件: sgp_annual5_3/acttrack/sale.go:74
   - 测试: 触发个人/房间维度开奖
   - 重点: 确认个人维度的uid字段

6. 🔴 **补充未实现埋点** - 影响6个埋点
   - #17: 实现层数挑战奖励埋点（level_reward）
   - #20: 实现触发魔王挑战埋点（trigger_boss）
   - #24: 确认Lottery Widget保底埋点（guarantee）
   - #25: 实现获得戒指双倍几率埋点（trigger_buff）
   - #26: 联系前端实现超过好友弹窗埋点（ShowH5）
   - #21: 修复选择奖励action不匹配（set_wish vs choose_reward）

7. 🔴 **补充需求文档** - 影响2个埋点
   - #9, #10: 补充随机/保底触发大礼物的字段定义

**P1（后续跟进）**:

8. ⚠️ **修复夺宝开奖uid字段** - 影响TC11-04
   - 文件: sgp_annual5_3/acttrack/sale.go:74
   - 修改: 个人维度条件排除uid字段（或确认uid=0符合需求）
   - 影响: 个人维度夺宝开奖埋点

9. ⚠️ **确认盲盒action** - 影响TC12-01, TC12-02
   - 选项1: 更新需求文档（action改为do_wheel_lottery）
   - 选项2: 修改Widget代码（action改为blind_box_get_reward）
   - 建议: 与需求方确认哪个action正确

10. ✅ **测试Gift Box Star Widget** - 影响1个埋点（#14）
    - 执行: 送礼盒礼物触发开奖
    - 验证: lottery_stage区分奖池、返金场景

11. ✅ **测试Extra Gift Widget** - 影响1个埋点（#8，如果配置了）
    - 执行: 确认Widget配置，触发礼物
    - 验证: send_gift埋点是否自动上报

**P2（长期工作）**:

12. 确认活动ID 6420 的埋点实现（代码中未找到）
13. 验证Task Widget（#3, #4）
14. 联系客户端验证埋点（#1, #2）
15. 执行完整回归测试

---

## 关于代码审查与实际测试的关系 ⚠️

**代码审查的价值**：
- ✅ 提前发现代码层面的逻辑错误
- ✅ 预测可能的问题和失败场景
- ✅ 提供修复建议和代码位置
- ✅ 节省测试人员的时间成本

**代码审查的局限性**：
- ❌ 无法验证埋点是否真实上报到数数平台
- ❌ 无法验证数据格式是否被数数平台正确解析
- ❌ 无法验证复杂场景下的数据准确性
- ❌ 无法验证Widget组件的实际行为
- ❌ 无法验证配置中心的配置是否正确

**测试人员的不可替代性**：
- 🔴 **埋点数据验证必须由测试人员执行**
- 🔴 **数据准确性验证必须由测试人员执行**
- 🔴 **多场景覆盖必须由测试人员执行**
- 🔴 **回归测试必须由测试人员执行**

> 💡 **总结**：代码审查是"提前发现问题"的手段，但无法替代"实际验证"。测试人员的工作是确保埋点在真实环境中正确运行，这是代码审查无法覆盖的关键环节。

---

## 附录：数数平台查询SQL示例

### 查询活动所有埋点

```sql
-- 查询活动ID 6362 和 6420 的所有埋点action
SELECT
  act_id,
  action,
  activity_type,
  COUNT(*) as count,
  COUNT(DISTINCT user_id) as unique_users,
  MIN(time) as first_report,
  MAX(time) as last_report
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
  AND time >= '2026-03-19 00:00:00'
GROUP BY act_id, action, activity_type
ORDER BY act_id, count DESC;
```

### 查询家族累消埋点

```sql
-- 家族完成任务
SELECT
  user_id,
  family_id,
  task_id,
  stage,
  task_name,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'complete_task'
  AND activity_type = 'temporary_event'
ORDER BY time DESC
LIMIT 100;

-- 家族Top5用户贡献
SELECT
  user_id,
  family_id,
  task_id,
  stage,
  use_coin,
  rank,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'complete_user'
  AND activity_type = 'temporary_event'
ORDER BY time DESC
LIMIT 100;
```

### 查询夺宝开奖埋点

```sql
-- 夺宝开奖（个人+房间维度）
SELECT
  user_id,
  type_str,
  coin,
  round_id,
  rid,
  uid,
  time
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'hunt_room'
  AND activity_type = 'temporary_event'
ORDER BY time DESC
LIMIT 100;

-- 统计个人维度和房间维度数量
SELECT
  type_str,
  COUNT(*) as count,
  AVG(coin) as avg_coin,
  MAX(coin) as max_coin
FROM ActivityTotal
WHERE act_id = 6362
  AND action = 'hunt_room'
GROUP BY type_str;
```

### 查询未实现埋点

```sql
-- 检查是否有do_wheel_lottery埋点
SELECT
  action,
  activity_type,
  COUNT(*) as count
FROM ActivityTotal
WHERE act_id IN (6362, 6420)
  AND action IN (
    'do_wheel_lottery',
    'send_gift',
    'blind_box_get_reward',
    'level_reward',
    'trigger_boss',
    'set_wish',
    'collect_exchange',
    'guarantee',
    'trigger_buff'
  )
GROUP BY action, activity_type
ORDER BY count DESC;
```

---

## 附录：配置值更新记录 ✅

### 配置来源

**API**: `POST https://config-admin-dev-api.weplayapp.com/config/get_key`

**查询参数**:
```json
{
  "key": "6362",  // 或 "6420"
  "region": "C",
  "namespace": "activity"
}
```

**配置文件位置**:
- 活动6362完整配置: `config_6362.json`
- 活动6420完整配置: `config_6420.json`
- Widget配置摘要: `五周年三阶段_Widget配置摘要_6362_6420.md`

---

### 活动6362 配置快速查找表

#### Lottery Widget (box_type)
| box_type | 配置名称 | 用于埋点测试 |
|----------|---------|-------------|
| 1 | 周年庆宝箱抽奖 | #7, #13, #16 |
| 2 | 三星奖池 | #7, #15, #16 |
| 3 | 四星奖池 | #7, #16 |
| 4 | 五星奖池 | #7, #16 |
| 5 | 充能抽奖 | #16 |
| 6 | 盲盒幸运抽奖 | #12 |
| 50 | 送大礼物得座驾 | #16 |

#### Collect Chip Widget (chip_id)
| chip_id | 配置名称 | 用于埋点测试 |
|---------|---------|-------------|
| 1 | 週年慶寶箱 | #18, #23 |
| 2 | 累消进度 | #22, #23 |
| 3 | 充能抽獎機會 | #23 |
| 4 | 幸運值碎片 | #12（盲盒幸运值） |
| 11 | 小丸子標識 | 夺宝玩法-猫猫虫标识 |
| 12 | 幸運標識 | 夺宝玩法-幸运标识 |

#### Hunting Config (后端配置)
| 配置字段 | 值 | 用于埋点测试 |
|---------|-----|-------------|
| special_gift_id | 1209934 | #11（小礼物ID） |
| coin_pool | 160000 | #11（初始金币池） |
| per_gift_coin | 15 | #11（每个小礼物增加金币） |
| round_gift_count | 10000 | #11（每轮小礼物数） |
| cat_flag_user_coin_ratio | 70 | #11（用户获得70%） |
| combo_limit | 100 | 连击次数限制 |

---

### 活动6420 配置快速查找表

#### Lottery Widget (box_type)
| box_type | 配置名称 | 用于埋点测试 |
|----------|---------|-------------|
| 1 | 爬塔抽奖小奖池 | #16 |
| 2 | 爬塔抽奖大奖池 | #16 |
| 3 | 开启魔王宝箱 | #19 |

#### Collect Chip Widget (chip_id)
| chip_id | 配置名称 | 用于埋点测试 |
|---------|---------|-------------|
| 1 | 魔王寶箱 | #18 |
| 2 | 自选戒指券 | #22, #23 |
| 3 | 鑰匙 | 相关玩法 |
| 4 | 未獲得獎勵 | 标识字段 |
| 5 | 登录app | 登录相关 |

#### Boss Attack Config (后端配置)
| 配置字段 | 值 | 说明 |
|---------|-----|------|
| boss_attack_coin_cost | 1000 | 攻击魔王消耗金币 |
| small_pool_coin_cost | 300 | 小奖池抽奖消耗 |
| big_pool_coin_cost | 600 | 大奖池抽奖消耗 |
| ring_select_chip_id | 2 | 自选戒指券chip_id |

---

### 配置与需求文档对比发现 ⚠️

#### 6362 活动差异

**需求文档说的 chip_id**:
- chip_id=1 → "魔王宝箱"
- chip_id=2 → "自选宝箱"

**实际配置中的 chip_id**:
- chip_id=1 → "週年慶寶箱" ⚠️ **不一致**
- chip_id=2 → "累消进度" ⚠️ **不一致**
- chip_id=11 → "小丸子標識"（可能对应需求中的"猫猫虫标识"）
- chip_id=12 → "幸運標識"（对应需求中的"幸运标识"）

**结论**:
- 需求文档可能是通用模板，实际配置值与需求文档不完全一致
- 测试时应以**真实配置值**为准
- 埋点验证时应检查 chip_name 是否与配置一致，而不是与需求文档一致

#### 6420 活动配置

活动 6420 的配置与需求文档更加匹配：
- chip_id=1 → "魔王寶箱" ✅
- chip_id=2 → "自选戒指券" ✅

---

### 更新记录

**v1.1 (2026-03-19)**:
- ✅ 添加配置中心真实数据
- ✅ 更新 Lottery Widget 测试示例（box_type 真实值）
- ✅ 更新 Collect Chip Widget 测试示例（chip_id, chip_name 真实值）
- ✅ 更新 Hunting Config 测试示例（金币计算使用真实配置）
- ✅ 添加配置快速查找表
- ✅ 标注配置来源和验证状态

**v1.0 (2026-03-19)**:
- 初始版本，基于代码审查
- 包含26个埋点的测试用例
- 使用模拟数据示例

---

**生成日期**: 2026-03-19
**文档版本**: v1.1（代码审查 + 配置验证版）
**维护者**: Claude (AI Assistant)

**说明**: 本报告基于静态代码分析和配置中心真实数据生成，测试数据示例使用真实配置值。但仍需测试人员通过实际验证来确认埋点正确性。
