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/
.claude/
CLAUDE.md
**/CLAUDE.md
.tmp/
......
# ActivitiesCover 页面测试指南
**测试日期**: 2026-02-09
**测试目标**: 验证 map_activity detail API 是否能覆盖 ActivitiesCover 页面的数据需求
---
## 📊 数据覆盖分析
### ✅ API 完全覆盖的字段
| 页面需求 | API 字段 | 数据类型 | 状态 |
|---------|---------|---------|------|
| 活动标题 | `tittle` | string | ✅ 完全匹配 |
| 封面图 | `cover` | string | ✅ 完全匹配 |
| 开始时间 | `begin_date` | string | ✅ 完全匹配 |
| 结束时间 | `end_date` | string | ✅ 完全匹配 |
| 活动是否开始 | `is_begin` | boolean | ✅ 完全匹配 |
| 活动是否结束 | `is_ended` | boolean | ✅ 完全匹配 |
| 首次打卡积分 | `first_checkin_points` | integer | ✅ 完全匹配 |
| 完成打卡积分 | `complete_points` | integer | ✅ 完全匹配 |
| 需要打卡次数 | `required_checkin_count` | integer | ✅ 完全匹配 |
### ⚠️ 需要转换的字段
| 页面需求 | 数据来源 | 转换逻辑 | 状态 |
|---------|---------|---------|------|
| 副标题 (`subtitle`) | 硬编码 | 固定文案 | ✅ 已处理 |
| 日期范围 (`dateRange`) | `begin_date` + `end_date` | 字符串拼接 | ✅ 已处理 |
| 活动描述 (`description`) | API 数据 | 模板生成 | ✅ 已处理 |
| 活动规则 (`rules`) | 积分相关字段 | 数组生成 | ✅ 已处理 |
| 奖励列表 (`rewards`) | 积分相关字段 | 数组生成 | ✅ 已处理 |
---
## 🔧 代码修改说明
### 1. 新增导入
```javascript
import { detailAPI } from '@/api/map_activity'
import { mockMapActivityDetailAPI } from '@/utils/mockData'
```
### 2. 添加环境变量
```javascript
// 开发环境使用 mock 数据,生产环境使用真实 API
const USE_MOCK_DATA = process.env.NODE_ENV === 'development'
```
### 3. 数据转换函数
```javascript
/**
* 将 API 数据转换为页面需要的 activityData 格式
* @param {Object} apiData - API 返回的活动详情数据
* @returns {Object} 页面活动数据对象
*/
const transformApiDataToActivityData = (apiData) => {
if (!apiData) return null
// 生成日期范围字符串
const dateRange = `${apiData.begin_date} - ${apiData.end_date}`
// 根据积分规则生成规则描述
const rules = [
`打卡任意1关,视为参与,奖励${apiData.first_checkin_points}积分`,
`打卡任意${apiData.required_checkin_count}关,视为完成,奖励${apiData.complete_points}积分`,
'不需要区分打卡点的先后次序'
]
// 生成奖励描述
const rewards = [
`首次打卡获得${apiData.first_checkin_points}积分`,
`完成${apiData.required_checkin_count}个打卡点获得${apiData.complete_points}积分`,
apiData.discount_title || '打卡点专属优惠'
]
return {
title: apiData.tittle || '活动标题',
subtitle: '探索城市魅力,感受时尚脉搏',
dateRange: dateRange,
posterUrl: apiData.cover || defaultPoster.value,
description: `欢迎参加${apiData.tittle}活动!`,
rules: rules,
rewards: rewards
}
}
```
### 4. 获取活动详情
```javascript
/**
* 获取活动详情
*/
const fetchActivityDetail = async () => {
try {
if (!activityId.value) {
console.warn('[ActivitiesCover] 未提供活动ID,跳过详情获取')
return
}
console.log('[ActivitiesCover] 开始获取活动详情, ID:', activityId.value)
// 根据环境选择真实 API 或 mock API
const response = USE_MOCK_DATA
? await mockMapActivityDetailAPI({ id: activityId.value })
: await detailAPI({ id: activityId.value })
if (response.code === 1 && response.data) {
console.log('[ActivitiesCover] 活动详情获取成功:', response.data)
// 转换 API 数据为页面格式
const transformedData = transformApiDataToActivityData(response.data)
if (transformedData) {
activityData.value = transformedData
// 更新默认海报图
if (response.data.cover) {
defaultPoster.value = response.data.cover
}
// 更新活动状态
activityStatus.value.is_begin = Boolean(response.data.is_begin)
activityStatus.value.is_ended = Boolean(response.data.is_ended)
}
}
} catch (error) {
console.error('[ActivitiesCover] 获取活动详情异常:', error)
}
}
```
### 5. 移除旧逻辑
- ❌ 移除了 `fetchActivityStatus` 函数(不再需要单独获取活动状态)
- ❌ 移除了 `getActivityStatusAPI` 导入
- ✅ 活动状态现在通过 `fetchActivityDetail` 统一获取
### 6. 动态积分规则显示
```vue
<!-- 积分规则说明 - 使用 v-for 动态渲染 -->
<view v-if="activityData.rules && activityData.rules.length" class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4 opacity-90">
<text class="text-blue-500 text-base font-medium block mb-2">积分规则说明:</text>
<text
v-for="(rule, index) in activityData.rules"
:key="index"
class="text-blue-500 text-sm leading-relaxed block mb-1"
style="padding-left: 20rpx; text-indent: -20rpx;"
>
• {{ rule }}
</text>
</view>
```
---
## 🧪 测试步骤
### 方式 1: Mock 数据测试(开发环境)
```bash
# 1. 启动开发服务器
pnpm run dev:weapp
# 2. 打开微信开发者工具,导入 dist 目录
# 3. 访问页面(带活动 ID 参数)
/pages/ActivitiesCover/index?id=1
# 或
/pages/ActivitiesCover/index?activity_id=1
# 4. 检查控制台日志,应该看到:
# [ActivitiesCover] 页面加载, 参数: {id: "1"}
# [ActivitiesCover] 开始获取活动详情, ID: 1
# [Mock] detailAPI - 活动详情,ID:1
# [ActivitiesCover] 活动详情获取成功: {...}
```
**预期结果**:
- ✅ 页面显示活动标题、封面图
- ✅ 日期范围正确显示
- ✅ 积分规则动态显示(不是硬编码)
- ✅ "立即参加" 按钮状态正确(根据活动状态)
### 方式 2: 真实 API 测试(生产环境)
```bash
# 1. 修改环境变量(确保不是开发环境)
# NODE_ENV=production
# 2. 重新构建
pnpm run build:weapp
# 3. 在微信开发者工具中测试
```
**预期结果**:
- ✅ 真实 API 数据正确显示
- ✅ 所有字段正确映射
---
## 📝 Mock 数据示例
### 输入参数
```javascript
{
id: "1"
}
```
### Mock 返回数据
```javascript
{
code: 1,
msg: "success",
data: {
url: "https://example.com/map",
id: "1",
cover: "https://picsum.photos/400/300?random=1",
tittle: "公园晨跑打卡",
begin_date: "2025.01.15",
end_date: "2025.02.28",
is_ended: false,
is_begin: true,
first_checkin_points: 10,
required_checkin_count: 5,
complete_points: 50,
discount_title: "打卡点优惠信息"
}
}
```
### 转换后的页面数据
```javascript
{
title: "公园晨跑打卡",
subtitle: "探索城市魅力,感受时尚脉搏",
dateRange: "2025.01.15 - 2025.02.28",
posterUrl: "https://picsum.photos/400/300?random=1",
description: "欢迎参加公园晨跑打卡活动!",
rules: [
"打卡任意1关,视为参与,奖励10积分",
"打卡任意5关,视为完成,奖励50积分",
"不需要区分打卡点的先后次序"
],
rewards: [
"首次打卡获得10积分",
"完成5个打卡点获得50积分",
"打卡点优惠信息"
]
}
```
---
## ✅ 验收标准
### 功能验收
- [ ] 页面能正确加载活动详情
- [ ] 活动标题正确显示
- [ ] 封面图正确显示
- [ ] 日期范围格式正确
- [ ] 积分规则动态生成并显示
- [ ] 活动状态(已开始/已结束)正确反映在按钮状态上
### 技术验收
- [ ] 开发环境使用 mock 数据
- [ ] 生产环境使用真实 API
- [ ] 数据转换逻辑正确
- [ ] 错误处理完善
- [ ] 控制台日志清晰
---
## 🐛 已知问题
### 1. API 字段拼写问题
**问题描述**: API 返回的字段是 `tittle`(拼写错误),不是 `title`
**解决方案**: 代码中使用 `apiData.tittle`,与 API 保持一致
### 2. 活动 ID 参数
**问题描述**: 可能使用 `id``activity_id` 作为参数名
**解决方案**:
```javascript
// 支持两种参数名
if (options.id) {
activityId.value = options.id
} else if (options.activity_id) {
activityId.value = options.activity_id
} else {
// 默认使用 ID: 1
activityId.value = '1'
}
```
---
## 📚 相关文件
- **页面代码**: `src/pages/ActivitiesCover/index.vue`
- **API 定义**: `src/api/map_activity.js`
- **Mock 数据**: `src/utils/mockData.js`
- **API 文档**: `docs/api-specs/map_activity/detail.md`
---
## 🎯 下一步
1. ✅ 完成功能开发
2. ⏳ 进行真机测试
3. ⏳ 测试不同活动 ID
4. ⏳ 测试边界情况(无网络、API 错误等)
5. ⏳ 优化用户体验
---
**测试人员**: Claude Code
**测试日期**: 2026-02-09
**测试状态**: ✅ 开发完成,等待测试
This diff is collapsed. Click to expand it.