hookehuyr

feat(ActivitiesCover): 集成 map_activity detail API

- 集成 detailAPI 获取活动详情数据
- 添加数据转换函数 transformApiDataToActivityData
- 移除单独的 fetchActivityStatus,统一通过 fetchActivityDetail 获取
- 积分规则改为动态渲染(v-for)
- 支持开发环境使用 mock 数据测试
- 创建测试指南文档

影响文件:
- src/pages/ActivitiesCover/index.vue
- docs/ActivitiesCover-测试指南.md
- .gitignore (添加 .tmp/ 目录)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -40,3 +40,4 @@ coverage/ ...@@ -40,3 +40,4 @@ coverage/
40 .claude/ 40 .claude/
41 CLAUDE.md 41 CLAUDE.md
42 **/CLAUDE.md 42 **/CLAUDE.md
43 +.tmp/
......
1 +# ActivitiesCover 页面测试指南
2 +
3 +**测试日期**: 2026-02-09
4 +**测试目标**: 验证 map_activity detail API 是否能覆盖 ActivitiesCover 页面的数据需求
5 +
6 +---
7 +
8 +## 📊 数据覆盖分析
9 +
10 +### ✅ API 完全覆盖的字段
11 +
12 +| 页面需求 | API 字段 | 数据类型 | 状态 |
13 +|---------|---------|---------|------|
14 +| 活动标题 | `tittle` | string | ✅ 完全匹配 |
15 +| 封面图 | `cover` | string | ✅ 完全匹配 |
16 +| 开始时间 | `begin_date` | string | ✅ 完全匹配 |
17 +| 结束时间 | `end_date` | string | ✅ 完全匹配 |
18 +| 活动是否开始 | `is_begin` | boolean | ✅ 完全匹配 |
19 +| 活动是否结束 | `is_ended` | boolean | ✅ 完全匹配 |
20 +| 首次打卡积分 | `first_checkin_points` | integer | ✅ 完全匹配 |
21 +| 完成打卡积分 | `complete_points` | integer | ✅ 完全匹配 |
22 +| 需要打卡次数 | `required_checkin_count` | integer | ✅ 完全匹配 |
23 +
24 +### ⚠️ 需要转换的字段
25 +
26 +| 页面需求 | 数据来源 | 转换逻辑 | 状态 |
27 +|---------|---------|---------|------|
28 +| 副标题 (`subtitle`) | 硬编码 | 固定文案 | ✅ 已处理 |
29 +| 日期范围 (`dateRange`) | `begin_date` + `end_date` | 字符串拼接 | ✅ 已处理 |
30 +| 活动描述 (`description`) | API 数据 | 模板生成 | ✅ 已处理 |
31 +| 活动规则 (`rules`) | 积分相关字段 | 数组生成 | ✅ 已处理 |
32 +| 奖励列表 (`rewards`) | 积分相关字段 | 数组生成 | ✅ 已处理 |
33 +
34 +---
35 +
36 +## 🔧 代码修改说明
37 +
38 +### 1. 新增导入
39 +
40 +```javascript
41 +import { detailAPI } from '@/api/map_activity'
42 +import { mockMapActivityDetailAPI } from '@/utils/mockData'
43 +```
44 +
45 +### 2. 添加环境变量
46 +
47 +```javascript
48 +// 开发环境使用 mock 数据,生产环境使用真实 API
49 +const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
50 +```
51 +
52 +### 3. 数据转换函数
53 +
54 +```javascript
55 +/**
56 + * 将 API 数据转换为页面需要的 activityData 格式
57 + * @param {Object} apiData - API 返回的活动详情数据
58 + * @returns {Object} 页面活动数据对象
59 + */
60 +const transformApiDataToActivityData = (apiData) => {
61 + if (!apiData) return null
62 +
63 + // 生成日期范围字符串
64 + const dateRange = `${apiData.begin_date} - ${apiData.end_date}`
65 +
66 + // 根据积分规则生成规则描述
67 + const rules = [
68 + `打卡任意1关,视为参与,奖励${apiData.first_checkin_points}积分`,
69 + `打卡任意${apiData.required_checkin_count}关,视为完成,奖励${apiData.complete_points}积分`,
70 + '不需要区分打卡点的先后次序'
71 + ]
72 +
73 + // 生成奖励描述
74 + const rewards = [
75 + `首次打卡获得${apiData.first_checkin_points}积分`,
76 + `完成${apiData.required_checkin_count}个打卡点获得${apiData.complete_points}积分`,
77 + apiData.discount_title || '打卡点专属优惠'
78 + ]
79 +
80 + return {
81 + title: apiData.tittle || '活动标题',
82 + subtitle: '探索城市魅力,感受时尚脉搏',
83 + dateRange: dateRange,
84 + posterUrl: apiData.cover || defaultPoster.value,
85 + description: `欢迎参加${apiData.tittle}活动!`,
86 + rules: rules,
87 + rewards: rewards
88 + }
89 +}
90 +```
91 +
92 +### 4. 获取活动详情
93 +
94 +```javascript
95 +/**
96 + * 获取活动详情
97 + */
98 +const fetchActivityDetail = async () => {
99 + try {
100 + if (!activityId.value) {
101 + console.warn('[ActivitiesCover] 未提供活动ID,跳过详情获取')
102 + return
103 + }
104 +
105 + console.log('[ActivitiesCover] 开始获取活动详情, ID:', activityId.value)
106 +
107 + // 根据环境选择真实 API 或 mock API
108 + const response = USE_MOCK_DATA
109 + ? await mockMapActivityDetailAPI({ id: activityId.value })
110 + : await detailAPI({ id: activityId.value })
111 +
112 + if (response.code === 1 && response.data) {
113 + console.log('[ActivitiesCover] 活动详情获取成功:', response.data)
114 +
115 + // 转换 API 数据为页面格式
116 + const transformedData = transformApiDataToActivityData(response.data)
117 + if (transformedData) {
118 + activityData.value = transformedData
119 +
120 + // 更新默认海报图
121 + if (response.data.cover) {
122 + defaultPoster.value = response.data.cover
123 + }
124 +
125 + // 更新活动状态
126 + activityStatus.value.is_begin = Boolean(response.data.is_begin)
127 + activityStatus.value.is_ended = Boolean(response.data.is_ended)
128 + }
129 + }
130 + } catch (error) {
131 + console.error('[ActivitiesCover] 获取活动详情异常:', error)
132 + }
133 +}
134 +```
135 +
136 +### 5. 移除旧逻辑
137 +
138 +- ❌ 移除了 `fetchActivityStatus` 函数(不再需要单独获取活动状态)
139 +- ❌ 移除了 `getActivityStatusAPI` 导入
140 +- ✅ 活动状态现在通过 `fetchActivityDetail` 统一获取
141 +
142 +### 6. 动态积分规则显示
143 +
144 +```vue
145 +<!-- 积分规则说明 - 使用 v-for 动态渲染 -->
146 +<view v-if="activityData.rules && activityData.rules.length" class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4 opacity-90">
147 + <text class="text-blue-500 text-base font-medium block mb-2">积分规则说明:</text>
148 + <text
149 + v-for="(rule, index) in activityData.rules"
150 + :key="index"
151 + class="text-blue-500 text-sm leading-relaxed block mb-1"
152 + style="padding-left: 20rpx; text-indent: -20rpx;"
153 + >
154 + • {{ rule }}
155 + </text>
156 +</view>
157 +```
158 +
159 +---
160 +
161 +## 🧪 测试步骤
162 +
163 +### 方式 1: Mock 数据测试(开发环境)
164 +
165 +```bash
166 +# 1. 启动开发服务器
167 +pnpm run dev:weapp
168 +
169 +# 2. 打开微信开发者工具,导入 dist 目录
170 +
171 +# 3. 访问页面(带活动 ID 参数)
172 +/pages/ActivitiesCover/index?id=1
173 +# 或
174 +/pages/ActivitiesCover/index?activity_id=1
175 +
176 +# 4. 检查控制台日志,应该看到:
177 +# [ActivitiesCover] 页面加载, 参数: {id: "1"}
178 +# [ActivitiesCover] 开始获取活动详情, ID: 1
179 +# [Mock] detailAPI - 活动详情,ID:1
180 +# [ActivitiesCover] 活动详情获取成功: {...}
181 +```
182 +
183 +**预期结果**:
184 +- ✅ 页面显示活动标题、封面图
185 +- ✅ 日期范围正确显示
186 +- ✅ 积分规则动态显示(不是硬编码)
187 +- ✅ "立即参加" 按钮状态正确(根据活动状态)
188 +
189 +### 方式 2: 真实 API 测试(生产环境)
190 +
191 +```bash
192 +# 1. 修改环境变量(确保不是开发环境)
193 +# NODE_ENV=production
194 +
195 +# 2. 重新构建
196 +pnpm run build:weapp
197 +
198 +# 3. 在微信开发者工具中测试
199 +```
200 +
201 +**预期结果**:
202 +- ✅ 真实 API 数据正确显示
203 +- ✅ 所有字段正确映射
204 +
205 +---
206 +
207 +## 📝 Mock 数据示例
208 +
209 +### 输入参数
210 +
211 +```javascript
212 +{
213 + id: "1"
214 +}
215 +```
216 +
217 +### Mock 返回数据
218 +
219 +```javascript
220 +{
221 + code: 1,
222 + msg: "success",
223 + data: {
224 + url: "https://example.com/map",
225 + id: "1",
226 + cover: "https://picsum.photos/400/300?random=1",
227 + tittle: "公园晨跑打卡",
228 + begin_date: "2025.01.15",
229 + end_date: "2025.02.28",
230 + is_ended: false,
231 + is_begin: true,
232 + first_checkin_points: 10,
233 + required_checkin_count: 5,
234 + complete_points: 50,
235 + discount_title: "打卡点优惠信息"
236 + }
237 +}
238 +```
239 +
240 +### 转换后的页面数据
241 +
242 +```javascript
243 +{
244 + title: "公园晨跑打卡",
245 + subtitle: "探索城市魅力,感受时尚脉搏",
246 + dateRange: "2025.01.15 - 2025.02.28",
247 + posterUrl: "https://picsum.photos/400/300?random=1",
248 + description: "欢迎参加公园晨跑打卡活动!",
249 + rules: [
250 + "打卡任意1关,视为参与,奖励10积分",
251 + "打卡任意5关,视为完成,奖励50积分",
252 + "不需要区分打卡点的先后次序"
253 + ],
254 + rewards: [
255 + "首次打卡获得10积分",
256 + "完成5个打卡点获得50积分",
257 + "打卡点优惠信息"
258 + ]
259 +}
260 +```
261 +
262 +---
263 +
264 +## ✅ 验收标准
265 +
266 +### 功能验收
267 +
268 +- [ ] 页面能正确加载活动详情
269 +- [ ] 活动标题正确显示
270 +- [ ] 封面图正确显示
271 +- [ ] 日期范围格式正确
272 +- [ ] 积分规则动态生成并显示
273 +- [ ] 活动状态(已开始/已结束)正确反映在按钮状态上
274 +
275 +### 技术验收
276 +
277 +- [ ] 开发环境使用 mock 数据
278 +- [ ] 生产环境使用真实 API
279 +- [ ] 数据转换逻辑正确
280 +- [ ] 错误处理完善
281 +- [ ] 控制台日志清晰
282 +
283 +---
284 +
285 +## 🐛 已知问题
286 +
287 +### 1. API 字段拼写问题
288 +
289 +**问题描述**: API 返回的字段是 `tittle`(拼写错误),不是 `title`
290 +
291 +**解决方案**: 代码中使用 `apiData.tittle`,与 API 保持一致
292 +
293 +### 2. 活动 ID 参数
294 +
295 +**问题描述**: 可能使用 `id``activity_id` 作为参数名
296 +
297 +**解决方案**:
298 +```javascript
299 +// 支持两种参数名
300 +if (options.id) {
301 + activityId.value = options.id
302 +} else if (options.activity_id) {
303 + activityId.value = options.activity_id
304 +} else {
305 + // 默认使用 ID: 1
306 + activityId.value = '1'
307 +}
308 +```
309 +
310 +---
311 +
312 +## 📚 相关文件
313 +
314 +- **页面代码**: `src/pages/ActivitiesCover/index.vue`
315 +- **API 定义**: `src/api/map_activity.js`
316 +- **Mock 数据**: `src/utils/mockData.js`
317 +- **API 文档**: `docs/api-specs/map_activity/detail.md`
318 +
319 +---
320 +
321 +## 🎯 下一步
322 +
323 +1. ✅ 完成功能开发
324 +2. ⏳ 进行真机测试
325 +3. ⏳ 测试不同活动 ID
326 +4. ⏳ 测试边界情况(无网络、API 错误等)
327 +5. ⏳ 优化用户体验
328 +
329 +---
330 +
331 +**测试人员**: Claude Code
332 +**测试日期**: 2026-02-09
333 +**测试状态**: ✅ 开发完成,等待测试
This diff is collapsed. Click to expand it.