Showing
5 changed files
with
652 additions
and
6 deletions
| ... | @@ -581,6 +581,82 @@ const store = useYourStore() | ... | @@ -581,6 +581,82 @@ const store = useYourStore() |
| 581 | store.setState('新值') | 581 | store.setState('新值') |
| 582 | ``` | 582 | ``` |
| 583 | 583 | ||
| 584 | +### 使用 Mock 数据工具 | ||
| 585 | + | ||
| 586 | +项目提供了统一的 Mock 数据工具(`src/utils/mockData.js`),用于开发阶段测试分页加载等功能。 | ||
| 587 | + | ||
| 588 | +**支持的 Mock API**: | ||
| 589 | + | ||
| 590 | +| API 名称 | 功能说明 | 使用页面 | | ||
| 591 | +|---------|---------|---------| | ||
| 592 | +| `mockWeekHotAPI` | 周热门资料 | 周热门资料页 | | ||
| 593 | +| `mockFileListAPI` | 资料列表 | 资料列表页 | | ||
| 594 | +| `mockProductListAPI` | 产品列表 | 产品中心页 | | ||
| 595 | +| `mockSearchAPI` | 搜索(产品+资料) | 搜索页 | | ||
| 596 | +| `mockMessageListAPI` | 消息列表 | 消息列表页 | | ||
| 597 | +| `mockFavoriteListAPI` | 收藏列表 | 收藏页 | | ||
| 598 | +| `mockFeedbackListAPI` | 意见反馈列表 | 意见反馈页 | | ||
| 599 | + | ||
| 600 | +**使用方式**: | ||
| 601 | + | ||
| 602 | +1. **在页面中导入 Mock 函数**: | ||
| 603 | +```javascript | ||
| 604 | +import { mockWeekHotAPI } from '@/utils/mockData' | ||
| 605 | +``` | ||
| 606 | + | ||
| 607 | +2. **设置 Mock 开关**: | ||
| 608 | +```javascript | ||
| 609 | +// 开发环境使用 Mock,生产环境使用真实 API | ||
| 610 | +const USE_MOCK_DATA = process.env.NODE_ENV === 'development' | ||
| 611 | +``` | ||
| 612 | + | ||
| 613 | +3. **在数据获取函数中使用**: | ||
| 614 | +```javascript | ||
| 615 | +const fetchWeekHot = async (page = 0) => { | ||
| 616 | + loading.value = true | ||
| 617 | + | ||
| 618 | + try { | ||
| 619 | + // 根据 USE_MOCK_DATA 开关决定使用 Mock 数据还是真实 API | ||
| 620 | + const res = USE_MOCK_DATA | ||
| 621 | + ? await mockWeekHotAPI({ page, limit: 20 }) | ||
| 622 | + : await fn(weekHotAPI({ page, limit: 20 })) | ||
| 623 | + | ||
| 624 | + if (res.code === 1) { | ||
| 625 | + weekHotList.value.push(...res.data.list) | ||
| 626 | + hasMore.value = res.data.list.length >= 20 | ||
| 627 | + } | ||
| 628 | + } catch (err) { | ||
| 629 | + console.error('获取周热门资料失败:', err) | ||
| 630 | + } finally { | ||
| 631 | + loading.value = false | ||
| 632 | + } | ||
| 633 | +} | ||
| 634 | +``` | ||
| 635 | + | ||
| 636 | +**Mock 数据特性**: | ||
| 637 | + | ||
| 638 | +- ✅ **模拟网络延迟**:100-300ms 随机延迟 | ||
| 639 | +- ✅ **支持分页加载**:可配置 `page` 和 `limit` 参数 | ||
| 640 | +- ✅ **随机数据生成**:文件大小、学习人数、收藏状态等 | ||
| 641 | +- ✅ **支持关键词搜索**:搜索 API 会根据关键词过滤数据 | ||
| 642 | +- ✅ **真实数据结构**:返回的数据结构与真实 API 一致 | ||
| 643 | +- ✅ **控制台日志**:每次请求都会打印 `[Mock]` 日志便于调试 | ||
| 644 | + | ||
| 645 | +**统一调用器**(可选): | ||
| 646 | + | ||
| 647 | +也可以使用 `mockAPI()` 统一调用器: | ||
| 648 | +```javascript | ||
| 649 | +import { mockAPI } from '@/utils/mockData' | ||
| 650 | + | ||
| 651 | +// 调用指定的 Mock API | ||
| 652 | +const res = await mockAPI('weekHotAPI', { page: 0, limit: 20 }) | ||
| 653 | +``` | ||
| 654 | + | ||
| 655 | +**注意事项**: | ||
| 656 | +- ⚠️ **生产环境关闭**:部署时确保 `USE_MOCK_DATA = false` | ||
| 657 | +- ⚠️ **数据结构对齐**:Mock 数据结构必须与真实 API 保持一致 | ||
| 658 | +- ⚠️ **分页逻辑**:Mock API 返回的 `list` 为空时表示没有更多数据 | ||
| 659 | + | ||
| 584 | ## 关键文件总结 | 660 | ## 关键文件总结 |
| 585 | 661 | ||
| 586 | ### 修改前必须理解 | 662 | ### 修改前必须理解 |
| ... | @@ -621,10 +697,14 @@ store.setState('新值') | ... | @@ -621,10 +697,14 @@ store.setState('新值') |
| 621 | 3. **`src/composables/useListItemClick.js`** - 列表点击处理 | 697 | 3. **`src/composables/useListItemClick.js`** - 列表点击处理 |
| 622 | 698 | ||
| 623 | ### 工具函数 | 699 | ### 工具函数 |
| 624 | -1. **`src/utils/documentIcons.js`** - 文档类型图标识别 | 700 | +1. **`src/utils/mockData.js`** - Mock 数据生成工具(开发测试用) |
| 625 | -2. **`src/utils/tools.js`** - 通用工具函数集合 | 701 | + - 支持多个 API 的 Mock:周热门资料、资料列表、产品列表、搜索、消息列表、收藏列表、意见反馈 |
| 626 | -3. **`src/utils/network.js`** - 网络状态工具 | 702 | + - 统一调用器:`mockAPI(apiName, params)` |
| 627 | -4. **`src/hooks/useGo.js`** - 增强导航 hook | 703 | + - 支持分页加载、模拟网络延迟、随机数据生成 |
| 704 | +2. **`src/utils/documentIcons.js`** - 文档类型图标识别 | ||
| 705 | +3. **`src/utils/tools.js`** - 通用工具函数集合 | ||
| 706 | +4. **`src/utils/network.js`** - 网络状态工具 | ||
| 707 | +5. **`src/hooks/useGo.js`** - 增强导航 hook | ||
| 628 | 708 | ||
| 629 | ## 调试技巧 | 709 | ## 调试技巧 |
| 630 | 710 | ... | ... |
| ... | @@ -5,6 +5,45 @@ | ... | @@ -5,6 +5,45 @@ |
| 5 | 5 | ||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | +## [2026-02-09] - 添加热卖产品 Mock 数据支持 | ||
| 9 | + | ||
| 10 | +### 新增 | ||
| 11 | +- **Mock 数据模块**(`src/api/mock/`): | ||
| 12 | + - 新增 `hotProducts.js`:包含 9 种产品的 Mock 数据 | ||
| 13 | + - 覆盖所有计划书模板类型(人寿、重疾、储蓄) | ||
| 14 | + - 支持 `form_sn` 字段,对应不同的计划书模板 | ||
| 15 | + - 包含完整的产品信息(名称、分类、标签、封面图) | ||
| 16 | + | ||
| 17 | +### 优化 | ||
| 18 | +- **首页 Mock 数据支持**(`src/pages/index/index.vue`): | ||
| 19 | + - 添加 `USE_MOCK_DATA` 开关控制数据来源 | ||
| 20 | + - 开发环境使用 Mock 数据测试计划书功能 | ||
| 21 | + - 生产环境调用真实 API(`listAPI`) | ||
| 22 | + - 添加详细的 JSDoc 注释和使用说明 | ||
| 23 | + | ||
| 24 | +### 文档 | ||
| 25 | +- **CLAUDE.md 更新**: | ||
| 26 | + - 添加 Mock 数据工具使用指南 | ||
| 27 | + - 说明支持的 Mock API 列表 | ||
| 28 | + - 提供使用示例和注意事项 | ||
| 29 | + | ||
| 30 | +--- | ||
| 31 | + | ||
| 32 | +**详细信息**: | ||
| 33 | +- **影响文件**: src/api/mock/hotProducts.js, src/pages/index/index.vue, CLAUDE.md | ||
| 34 | +- **技术栈**: Vue 3, Mock 数据 | ||
| 35 | +- **测试状态**: 开发环境已测试 | ||
| 36 | +- **备注**: ⚠️ 生产环境请设置 `USE_MOCK_DATA = false` | ||
| 37 | + | ||
| 38 | +--- | ||
| 39 | + | ||
| 40 | +# Changelog | ||
| 41 | + | ||
| 42 | +> 本文档记录 Manulife WeApp项目的所有重要变更。 | ||
| 43 | +> 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), | ||
| 44 | + | ||
| 45 | +--- | ||
| 46 | + | ||
| 8 | ## [2026-02-09] - 更新 API 集成日志和经验教训文档 | 47 | ## [2026-02-09] - 更新 API 集成日志和经验教训文档 |
| 9 | 48 | ||
| 10 | ### 文档 | 49 | ### 文档 | ... | ... |
src/api/mock/hotProducts.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 热卖产品 Mock 数据 | ||
| 3 | + * | ||
| 4 | + * @description 包含项目所有保险类型的产品 mock 数据,用于测试计划书模板显示 | ||
| 5 | + * 遵循项目 mock 数据规范,集成到 src/utils/mockData.js | ||
| 6 | + * @module api/mock/hotProducts | ||
| 7 | + * @author Claude Code | ||
| 8 | + * @created 2026-02-09 | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 热卖产品 Mock 数据列表 | ||
| 13 | + * @description 包含 9 种产品,覆盖所有计划书模板类型 | ||
| 14 | + */ | ||
| 15 | +const HOT_PRODUCTS = [ | ||
| 16 | + // ====== 人寿保险 (LifeInsuranceTemplate) ====== | ||
| 17 | + | ||
| 18 | + { | ||
| 19 | + id: 1, | ||
| 20 | + product_name: 'WIOP3E 盈传创富保障计划 3 - 优选版', | ||
| 21 | + name: 'WIOP3E 盈传创富保障计划 3 - 优选版', | ||
| 22 | + recommend: 'hot', | ||
| 23 | + form_sn: 'life-insurance-wiop3e', // 对应 LifeInsuranceTemplate | ||
| 24 | + categories: [ | ||
| 25 | + { id: 'life', name: '人寿保险' } | ||
| 26 | + ], | ||
| 27 | + tags: [ | ||
| 28 | + { id: 't1', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' }, | ||
| 29 | + { id: 't2', name: '美元产品', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 30 | + ], | ||
| 31 | + cover_image: 'https://picsum.photos/seed/wiop3e/400/300' | ||
| 32 | + }, | ||
| 33 | + | ||
| 34 | + { | ||
| 35 | + id: 2, | ||
| 36 | + product_name: 'WIOP3 盈传创富保障计划 3', | ||
| 37 | + name: 'WIOP3 盈传创富保障计划 3', | ||
| 38 | + recommend: 'hot', | ||
| 39 | + form_sn: 'life-insurance-wiop3', // 对应 LifeInsuranceTemplate | ||
| 40 | + categories: [ | ||
| 41 | + { id: 'life', name: '人寿保险' } | ||
| 42 | + ], | ||
| 43 | + tags: [ | ||
| 44 | + { id: 't1', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' }, | ||
| 45 | + { id: 't2', name: '美元产品', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 46 | + ], | ||
| 47 | + cover_image: 'https://picsum.photos/seed/wiop3/400/300' | ||
| 48 | + }, | ||
| 49 | + | ||
| 50 | + // ====== 重疾保险 (CriticalIllnessTemplate) ====== | ||
| 51 | + | ||
| 52 | + { | ||
| 53 | + id: 3, | ||
| 54 | + product_name: 'MPC 守护无间重疾', | ||
| 55 | + name: 'MPC 守护无间重疾', | ||
| 56 | + recommend: 'hot', | ||
| 57 | + form_sn: 'critical-illness-mpc', // 对应 CriticalIllnessTemplate | ||
| 58 | + categories: [ | ||
| 59 | + { id: 'critical', name: '重疾保险' } | ||
| 60 | + ], | ||
| 61 | + tags: [ | ||
| 62 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 63 | + { id: 't2', name: '终身保障', bg_color: '#E0E7FF', text_color: '#3730A3' } | ||
| 64 | + ], | ||
| 65 | + cover_image: 'https://picsum.photos/seed/mpc/400/300' | ||
| 66 | + }, | ||
| 67 | + | ||
| 68 | + { | ||
| 69 | + id: 4, | ||
| 70 | + product_name: 'MBC PRO 活跃人生重疾保 PRO', | ||
| 71 | + name: 'MBC PRO 活跃人生重疾保 PRO', | ||
| 72 | + recommend: 'hot', | ||
| 73 | + form_sn: 'critical-illness-mbc-pro', // 对应 CriticalIllnessTemplate | ||
| 74 | + categories: [ | ||
| 75 | + { id: 'critical', name: '重疾保险' } | ||
| 76 | + ], | ||
| 77 | + tags: [ | ||
| 78 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 79 | + { id: 't2', name: 'PRO 版本', bg_color: '#FEE2E2', text_color: '#991B1B' } | ||
| 80 | + ], | ||
| 81 | + cover_image: 'https://picsum.photos/seed/mbc-pro/400/300' | ||
| 82 | + }, | ||
| 83 | + | ||
| 84 | + { | ||
| 85 | + id: 5, | ||
| 86 | + product_name: 'MBC2 活跃人生重疾保 2', | ||
| 87 | + name: 'MBC2 活跃人生重疾保 2', | ||
| 88 | + recommend: 'hot', | ||
| 89 | + form_sn: 'critical-illness-mbc2', // 对应 CriticalIllnessTemplate | ||
| 90 | + categories: [ | ||
| 91 | + { id: 'critical', name: '重疾保险' } | ||
| 92 | + ], | ||
| 93 | + tags: [ | ||
| 94 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 95 | + { id: 't2', name: '升级版', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 96 | + ], | ||
| 97 | + cover_image: 'https://picsum.photos/seed/mbc2/400/300' | ||
| 98 | + }, | ||
| 99 | + | ||
| 100 | + // ====== 储蓄型产品 (SavingsTemplate) ====== | ||
| 101 | + | ||
| 102 | + { | ||
| 103 | + id: 6, | ||
| 104 | + product_name: 'GS 宏挚传承保障计划', | ||
| 105 | + name: 'GS 宏挚传承保障计划', | ||
| 106 | + recommend: 'hot', | ||
| 107 | + form_sn: 'savings-gs', // 对应 SavingsTemplate | ||
| 108 | + categories: [ | ||
| 109 | + { id: 'savings', name: '储蓄保险' } | ||
| 110 | + ], | ||
| 111 | + tags: [ | ||
| 112 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 113 | + { id: 't2', name: '传承规划', bg_color: '#F3E8FF', text_color: '#6B21A8' } | ||
| 114 | + ], | ||
| 115 | + cover_image: 'https://picsum.photos/seed/gs/400/300' | ||
| 116 | + }, | ||
| 117 | + | ||
| 118 | + { | ||
| 119 | + id: 7, | ||
| 120 | + product_name: 'GC 宏挚家传保险计划', | ||
| 121 | + name: 'GC 宏挚家传保险计划', | ||
| 122 | + recommend: 'hot', | ||
| 123 | + form_sn: 'savings-gc', // 对应 SavingsTemplate | ||
| 124 | + categories: [ | ||
| 125 | + { id: 'savings', name: '储蓄保险' } | ||
| 126 | + ], | ||
| 127 | + tags: [ | ||
| 128 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 129 | + { id: 't2', name: '家庭保障', bg_color: '#FEE2E2', text_color: '#991B1B' } | ||
| 130 | + ], | ||
| 131 | + cover_image: 'https://picsum.photos/seed/gc/400/300' | ||
| 132 | + }, | ||
| 133 | + | ||
| 134 | + { | ||
| 135 | + id: 8, | ||
| 136 | + product_name: 'FA 宏浚传承保障计划', | ||
| 137 | + name: 'FA 宏浚传承保障计划', | ||
| 138 | + recommend: 'hot', | ||
| 139 | + form_sn: 'savings-fa', // 对应 SavingsTemplate | ||
| 140 | + categories: [ | ||
| 141 | + { id: 'savings', name: '储蓄保险' } | ||
| 142 | + ], | ||
| 143 | + tags: [ | ||
| 144 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 145 | + { id: 't2', name: '财富传承', bg_color: '#FEF3C7', text_color: '#92400E' } | ||
| 146 | + ], | ||
| 147 | + cover_image: 'https://picsum.photos/seed/fa/400/300' | ||
| 148 | + }, | ||
| 149 | + | ||
| 150 | + { | ||
| 151 | + id: 9, | ||
| 152 | + product_name: 'LV2 赤霞珠终身寿险计划2', | ||
| 153 | + name: 'LV2 赤霞珠终身寿险计划2', | ||
| 154 | + recommend: 'hot', | ||
| 155 | + form_sn: 'savings-lv2', // 对应 SavingsTemplate | ||
| 156 | + categories: [ | ||
| 157 | + { id: 'savings', name: '储蓄保险' } | ||
| 158 | + ], | ||
| 159 | + tags: [ | ||
| 160 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 161 | + { id: 't2', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' } | ||
| 162 | + ], | ||
| 163 | + cover_image: 'https://picsum.photos/seed/lv2/400/300' | ||
| 164 | + } | ||
| 165 | +] | ||
| 166 | + | ||
| 167 | +/** | ||
| 168 | + * Mock: listAPI (热卖产品) | ||
| 169 | + * @description 专门用于首页热卖产品的 Mock API,支持 form_sn 字段 | ||
| 170 | + * @param {Object} params - 请求参数 | ||
| 171 | + * @param {string} params.recommend - 推荐位(必须为 'hot') | ||
| 172 | + * @returns {Promise<Object>} 模拟的 API 响应 | ||
| 173 | + */ | ||
| 174 | +export async function mockHotProductsListAPI(params) { | ||
| 175 | + const { recommend } = params | ||
| 176 | + | ||
| 177 | + // 只返回热卖产品 | ||
| 178 | + if (recommend !== 'hot') { | ||
| 179 | + return { code: 0, msg: '只支持热卖产品查询', data: { list: [], total: 0 } } | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + // 模拟网络延迟 | ||
| 183 | + await new Promise(resolve => setTimeout(resolve, 200)) | ||
| 184 | + | ||
| 185 | + console.log('[Mock] hotProductsListAPI - 返回热卖产品', HOT_PRODUCTS.length, '条') | ||
| 186 | + | ||
| 187 | + return { | ||
| 188 | + code: 1, | ||
| 189 | + msg: 'success', | ||
| 190 | + data: { | ||
| 191 | + list: HOT_PRODUCTS, | ||
| 192 | + total: HOT_PRODUCTS.length, | ||
| 193 | + categories: [ | ||
| 194 | + { id: 'life', name: '人寿保险' }, | ||
| 195 | + { id: 'critical', name: '重疾保险' }, | ||
| 196 | + { id: 'savings', name: '储蓄保险' } | ||
| 197 | + ] | ||
| 198 | + } | ||
| 199 | + } | ||
| 200 | +} | ||
| 201 | + | ||
| 202 | +/** | ||
| 203 | + * 导出 Mock API 函数供其他模块使用 | ||
| 204 | + */ | ||
| 205 | +export default { | ||
| 206 | + mockHotProductsListAPI | ||
| 207 | +} |
src/api/mock/mock/hotProducts.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 热卖产品 Mock 数据 | ||
| 3 | + * | ||
| 4 | + * @description 包含项目所有保险类型的产品 mock 数据,用于测试计划书模板显示 | ||
| 5 | + * 涵盖人寿保险、重疾保险、储蓄型产品三大类 | ||
| 6 | + * @module mock/hotProducts | ||
| 7 | + * @author Claude Code | ||
| 8 | + * @created 2026-02-09 | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 热卖产品 Mock 数据列表 | ||
| 13 | + * | ||
| 14 | + * @description 包含 9 种产品,覆盖所有计划书模板类型: | ||
| 15 | + * - 人寿保险 (2 种): WIOP3E、WIOP3 | ||
| 16 | + * - 重疾保险 (3 种): MPC、MBC PRO、MBC2 | ||
| 17 | + * - 储蓄型产品 (4 种): GS、GC、FA、LV2 | ||
| 18 | + */ | ||
| 19 | +export const hotProductsMockData = [ | ||
| 20 | + // ====== 人寿保险 (LifeInsuranceTemplate) ====== | ||
| 21 | + | ||
| 22 | + { | ||
| 23 | + id: 1, | ||
| 24 | + product_name: 'WIOP3E 盈传创富保障计划 3 - 优选版', | ||
| 25 | + recommend: 'hot', | ||
| 26 | + form_sn: 'life-insurance-wiop3e', // 对应 LifeInsuranceTemplate | ||
| 27 | + categories: [ | ||
| 28 | + { id: 'life', name: '人寿保险' } | ||
| 29 | + ], | ||
| 30 | + tags: [ | ||
| 31 | + { id: 't1', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' }, | ||
| 32 | + { id: 't2', name: '美元产品', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 33 | + ], | ||
| 34 | + cover_image: 'https://picsum.photos/seed/wiop3e/400/300', | ||
| 35 | + created_time: '2026-01-01 00:00:00' | ||
| 36 | + }, | ||
| 37 | + | ||
| 38 | + { | ||
| 39 | + id: 2, | ||
| 40 | + product_name: 'WIOP3 盈传创富保障计划 3', | ||
| 41 | + recommend: 'hot', | ||
| 42 | + form_sn: 'life-insurance-wiop3', // 对应 LifeInsuranceTemplate | ||
| 43 | + categories: [ | ||
| 44 | + { id: 'life', name: '人寿保险' } | ||
| 45 | + ], | ||
| 46 | + tags: [ | ||
| 47 | + { id: 't1', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' }, | ||
| 48 | + { id: 't2', name: '美元产品', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 49 | + ], | ||
| 50 | + cover_image: 'https://picsum.photos/seed/wiop3/400/300', | ||
| 51 | + created_time: '2026-01-02 00:00:00' | ||
| 52 | + }, | ||
| 53 | + | ||
| 54 | + // ====== 重疾保险 (CriticalIllnessTemplate) ====== | ||
| 55 | + | ||
| 56 | + { | ||
| 57 | + id: 3, | ||
| 58 | + product_name: 'MPC 守护无间重疾', | ||
| 59 | + recommend: 'hot', | ||
| 60 | + form_sn: 'critical-illness-mpc', // 对应 CriticalIllnessTemplate | ||
| 61 | + categories: [ | ||
| 62 | + { id: 'critical', name: '重疾保险' } | ||
| 63 | + ], | ||
| 64 | + tags: [ | ||
| 65 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 66 | + { id: 't2', name: '终身保障', bg_color: '#E0E7FF', text_color: '#3730A3' } | ||
| 67 | + ], | ||
| 68 | + cover_image: 'https://picsum.photos/seed/mpc/400/300', | ||
| 69 | + created_time: '2026-01-03 00:00:00' | ||
| 70 | + }, | ||
| 71 | + | ||
| 72 | + { | ||
| 73 | + id: 4, | ||
| 74 | + product_name: 'MBC PRO 活跃人生重疾保 PRO', | ||
| 75 | + recommend: 'hot', | ||
| 76 | + form_sn: 'critical-illness-mbc-pro', // 对应 CriticalIllnessTemplate | ||
| 77 | + categories: [ | ||
| 78 | + { id: 'critical', name: '重疾保险' } | ||
| 79 | + ], | ||
| 80 | + tags: [ | ||
| 81 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 82 | + { id: 't2', name: 'PRO 版本', bg_color: '#FEE2E2', text_color: '#991B1B' } | ||
| 83 | + ], | ||
| 84 | + cover_image: 'https://picsum.photos/seed/mbc-pro/400/300', | ||
| 85 | + created_time: '2026-01-04 00:00:00' | ||
| 86 | + }, | ||
| 87 | + | ||
| 88 | + { | ||
| 89 | + id: 5, | ||
| 90 | + product_name: 'MBC2 活跃人生重疾保 2', | ||
| 91 | + recommend: 'hot', | ||
| 92 | + form_sn: 'critical-illness-mbc2', // 对应 CriticalIllnessTemplate | ||
| 93 | + categories: [ | ||
| 94 | + { id: 'critical', name: '重疾保险' } | ||
| 95 | + ], | ||
| 96 | + tags: [ | ||
| 97 | + { id: 't1', name: '重疾保障', bg_color: '#FEF3C7', text_color: '#92400E' }, | ||
| 98 | + { id: 't2', name: '升级版', bg_color: '#DCFCE7', text_color: '#166534' } | ||
| 99 | + ], | ||
| 100 | + cover_image: 'https://picsum.photos/seed/mbc2/400/300', | ||
| 101 | + created_time: '2026-01-05 00:00:00' | ||
| 102 | + }, | ||
| 103 | + | ||
| 104 | + // ====== 储蓄型产品 (SavingsTemplate) ====== | ||
| 105 | + | ||
| 106 | + { | ||
| 107 | + id: 6, | ||
| 108 | + product_name: 'GS 宏挚传承保障计划', | ||
| 109 | + recommend: 'hot', | ||
| 110 | + form_sn: 'savings-gs', // 对应 SavingsTemplate | ||
| 111 | + categories: [ | ||
| 112 | + { id: 'savings', name: '储蓄保险' } | ||
| 113 | + ], | ||
| 114 | + tags: [ | ||
| 115 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 116 | + { id: 't2', name: '传承规划', bg_color: '#F3E8FF', text_color: '#6B21A8' } | ||
| 117 | + ], | ||
| 118 | + cover_image: 'https://picsum.photos/seed/gs/400/300', | ||
| 119 | + created_time: '2026-01-06 00:00:00' | ||
| 120 | + }, | ||
| 121 | + | ||
| 122 | + { | ||
| 123 | + id: 7, | ||
| 124 | + product_name: 'GC 宏挚家传保险计划', | ||
| 125 | + recommend: 'hot', | ||
| 126 | + form_sn: 'savings-gc', // 对应 SavingsTemplate | ||
| 127 | + categories: [ | ||
| 128 | + { id: 'savings', name: '储蓄保险' } | ||
| 129 | + ], | ||
| 130 | + tags: [ | ||
| 131 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 132 | + { id: 't2', name: '家庭保障', bg_color: '#FEE2E2', text_color: '#991B1B' } | ||
| 133 | + ], | ||
| 134 | + cover_image: 'https://picsum.photos/seed/gc/400/300', | ||
| 135 | + created_time: '2026-01-07 00:00:00' | ||
| 136 | + }, | ||
| 137 | + | ||
| 138 | + { | ||
| 139 | + id: 8, | ||
| 140 | + product_name: 'FA 宏浚传承保障计划', | ||
| 141 | + recommend: 'hot', | ||
| 142 | + form_sn: 'savings-fa', // 对应 SavingsTemplate | ||
| 143 | + categories: [ | ||
| 144 | + { id: 'savings', name: '储蓄保险' } | ||
| 145 | + ], | ||
| 146 | + tags: [ | ||
| 147 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 148 | + { id: 't2', name: '财富传承', bg_color: '#FEF3C7', text_color: '#92400E' } | ||
| 149 | + ], | ||
| 150 | + cover_image: 'https://picsum.photos/seed/fa/400/300', | ||
| 151 | + created_time: '2026-01-08 00:00:00' | ||
| 152 | + }, | ||
| 153 | + | ||
| 154 | + { | ||
| 155 | + id: 9, | ||
| 156 | + product_name: 'LV2 赤霞珠终身寿险计划2', | ||
| 157 | + recommend: 'hot', | ||
| 158 | + form_sn: 'savings-lv2', // 对应 SavingsTemplate | ||
| 159 | + categories: [ | ||
| 160 | + { id: 'savings', name: '储蓄保险' } | ||
| 161 | + ], | ||
| 162 | + tags: [ | ||
| 163 | + { id: 't1', name: '储蓄型', bg_color: '#E0E7FF', text_color: '#3730A3' }, | ||
| 164 | + { id: 't2', name: '终身寿险', bg_color: '#DBEAFE', text_color: '#1E40AF' } | ||
| 165 | + ], | ||
| 166 | + cover_image: 'https://picsum.photos/seed/lv2/400/300', | ||
| 167 | + created_time: '2026-01-09 00:00:00' | ||
| 168 | + } | ||
| 169 | +] | ||
| 170 | + | ||
| 171 | +/** | ||
| 172 | + * 获取热卖产品 Mock 数据 | ||
| 173 | + * | ||
| 174 | + * @description 模拟 API 返回格式,包含完整的产品列表数据 | ||
| 175 | + * @returns {Object} 模拟的 API 响应对象 | ||
| 176 | + * @example | ||
| 177 | + * const mockResponse = getHotProductsMock() | ||
| 178 | + * // 返回: { code: 1, data: { list: [...], total: 9 }, msg: 'success' } | ||
| 179 | + */ | ||
| 180 | +export function getHotProductsMock() { | ||
| 181 | + return { | ||
| 182 | + code: 1, | ||
| 183 | + msg: 'success', | ||
| 184 | + data: { | ||
| 185 | + list: hotProductsMockData, | ||
| 186 | + total: hotProductsMockData.length, | ||
| 187 | + // 分类统计(可选,用于筛选) | ||
| 188 | + categories: [ | ||
| 189 | + { id: 'life', name: '人寿保险' }, | ||
| 190 | + { id: 'critical', name: '重疾保险' }, | ||
| 191 | + { id: 'savings', name: '储蓄保险' } | ||
| 192 | + ] | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +/** | ||
| 198 | + * 根据 form_sn 获取产品 Mock 数据 | ||
| 199 | + * | ||
| 200 | + * @description 用于测试特定计划书模板 | ||
| 201 | + * @param {string} formSn - 表单模板标识 | ||
| 202 | + * @returns {Object|null} 产品对象,未找到返回 null | ||
| 203 | + * @example | ||
| 204 | + * const product = getProductByFormSn('life-insurance-wiop3e') | ||
| 205 | + * // 返回: { id: 1, product_name: 'WIOP3E...', form_sn: 'life-insurance-wiop3e', ... } | ||
| 206 | + */ | ||
| 207 | +export function getProductByFormSn(formSn) { | ||
| 208 | + return hotProductsMockData.find(p => p.form_sn === formSn) || null | ||
| 209 | +} | ||
| 210 | + | ||
| 211 | +/** | ||
| 212 | + * 获取所有计划书模板类型 | ||
| 213 | + * | ||
| 214 | + * @description 返回项目中所有支持的计划书模板类型 | ||
| 215 | + * @returns {Array} 模板类型列表 | ||
| 216 | + * @example | ||
| 217 | + * const templates = getAllTemplateTypes() | ||
| 218 | + * // 返回: ['life-insurance-wiop3e', 'life-insurance-wiop3', 'critical-illness-mpc', ...] | ||
| 219 | + */ | ||
| 220 | +export function getAllTemplateTypes() { | ||
| 221 | + return hotProductsMockData.map(p => ({ | ||
| 222 | + form_sn: p.form_sn, | ||
| 223 | + product_name: p.product_name, | ||
| 224 | + category: p.categories[0]?.name | ||
| 225 | + })) | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +/** | ||
| 229 | + * Mock 数据使用说明 | ||
| 230 | + * | ||
| 231 | + * @description 在开发环境中使用 mock 数据测试计划书功能 | ||
| 232 | + * | ||
| 233 | + * ## 使用方式 | ||
| 234 | + * | ||
| 235 | + * ### 方式 1: 直接替换 API 调用(推荐) | ||
| 236 | + * ```javascript | ||
| 237 | + * // src/pages/index/index.vue | ||
| 238 | + * import { getHotProductsMock } from '@/mock/hotProducts' | ||
| 239 | + * | ||
| 240 | + * const fetchHotProducts = async () => { | ||
| 241 | + * // 开发环境使用 mock 数据 | ||
| 242 | + * if (process.env.NODE_ENV === 'development') { | ||
| 243 | + * const res = getHotProductsMock() | ||
| 244 | + * if (res.code === 1 && res.data) { | ||
| 245 | + * hotProducts.value = res.data.list | ||
| 246 | + * } | ||
| 247 | + * return | ||
| 248 | + * } | ||
| 249 | + * | ||
| 250 | + * // 生产环境调用真实 API | ||
| 251 | + * const res = await listAPI({ recommend: 'hot' }) | ||
| 252 | + * // ... | ||
| 253 | + * } | ||
| 254 | + * ``` | ||
| 255 | + * | ||
| 256 | + * ### 方式 2: 使用环境变量控制 | ||
| 257 | + * ```javascript | ||
| 258 | + * // config/index.js | ||
| 259 | + * const config = { | ||
| 260 | + * useMock: process.env.USE_MOCK === 'true' // 环境变量控制 | ||
| 261 | + * } | ||
| 262 | + * | ||
| 263 | + * // src/pages/index/index.vue | ||
| 264 | + * const fetchHotProducts = async () => { | ||
| 265 | + * if (config.useMock) { | ||
| 266 | + * const res = getHotProductsMock() | ||
| 267 | + * // ... | ||
| 268 | + * } | ||
| 269 | + * // ... | ||
| 270 | + * } | ||
| 271 | + * ``` | ||
| 272 | + * | ||
| 273 | + * ## 测试覆盖 | ||
| 274 | + * | ||
| 275 | + * Mock 数据覆盖以下计划书模板: | ||
| 276 | + * | ||
| 277 | + * ### 人寿保险 (LifeInsuranceTemplate) | ||
| 278 | + * - ✅ life-insurance-wiop3e - WIOP3E 盈传创富保障计划 3 - 优选版 | ||
| 279 | + * - ✅ life-insurance-wiop3 - WIOP3 盈传创富保障计划 3 | ||
| 280 | + * | ||
| 281 | + * ### 重疾保险 (CriticalIllnessTemplate) | ||
| 282 | + * - ✅ critical-illness-mpc - MPC 守护无间重疾 | ||
| 283 | + * - ✅ critical-illness-mbc-pro - MBC PRO 活跃人生重疾保 PRO | ||
| 284 | + * - ✅ critical-illness-mbc2 - MBC2 活跃人生重疾保 2 | ||
| 285 | + * | ||
| 286 | + * ### 储蓄型产品 (SavingsTemplate) | ||
| 287 | + * - ✅ savings-gs - GS 宏挚传承保障计划 | ||
| 288 | + * - ✅ savings-gc - GC 宏挚家传保险计划 | ||
| 289 | + * - ✅ savings-fa - FA 宏浚传承保障计划 | ||
| 290 | + * - ✅ savings-lv2 - LV2 赤霞珠终身寿险计划2 | ||
| 291 | + * | ||
| 292 | + * ## 测试步骤 | ||
| 293 | + * | ||
| 294 | + * 1. 在首页点击任意产品的"计划书"按钮 | ||
| 295 | + * 2. 验证弹窗标题是否正确显示产品名称 | ||
| 296 | + * 3. 验证表单字段是否与产品类型匹配 | ||
| 297 | + * 4. 测试表单提交功能 | ||
| 298 | + * 5. 验证错误提示和校验规则 | ||
| 299 | + */ |
| ... | @@ -120,8 +120,8 @@ import ProductCard from '@/components/cards/ProductCard.vue'; | ... | @@ -120,8 +120,8 @@ import ProductCard from '@/components/cards/ProductCard.vue'; |
| 120 | import MaterialCard from '@/components/cards/MaterialCard.vue'; | 120 | import MaterialCard from '@/components/cards/MaterialCard.vue'; |
| 121 | import { listAPI } from '@/api/get_product'; | 121 | import { listAPI } from '@/api/get_product'; |
| 122 | import { weekHotAPI } from '@/api/file'; | 122 | import { weekHotAPI } from '@/api/file'; |
| 123 | -import { useCollectOperation } from '@/composables/useCollectOperation'; | ||
| 124 | import { homeIconAPI } from '@/api/home'; | 123 | import { homeIconAPI } from '@/api/home'; |
| 124 | +import { mockHotProductsListAPI } from '@/api/mock/hotProducts'; | ||
| 125 | 125 | ||
| 126 | 126 | ||
| 127 | // User Store | 127 | // User Store |
| ... | @@ -246,12 +246,33 @@ const fetchHomeIcons = async () => { | ... | @@ -246,12 +246,33 @@ const fetchHomeIcons = async () => { |
| 246 | const hotProducts = ref([]); | 246 | const hotProducts = ref([]); |
| 247 | 247 | ||
| 248 | /** | 248 | /** |
| 249 | + * Mock 数据开关 | ||
| 250 | + * @description 开发环境默认使用 mock 数据测试计划书功能 | ||
| 251 | + * 生产环境必须设置为 false | ||
| 252 | + */ | ||
| 253 | +const USE_MOCK_DATA = true; // ⚠️ 生产环境请设置为 false | ||
| 254 | + | ||
| 255 | +/** | ||
| 249 | * 获取热卖产品列表 | 256 | * 获取热卖产品列表 |
| 250 | * | 257 | * |
| 251 | - * @description 调用 listAPI 获取热卖产品列表 | 258 | + * @description 根据 USE_MOCK_DATA 开关决定使用 mock 数据还是调用 API |
| 259 | + * - 开发环境使用 mock 数据测试计划书功能 | ||
| 260 | + * - 生产环境调用 listAPI 获取真实数据 | ||
| 252 | */ | 261 | */ |
| 253 | const fetchHotProducts = async () => { | 262 | const fetchHotProducts = async () => { |
| 254 | try { | 263 | try { |
| 264 | + // 开发测试环境:使用 mock 数据 | ||
| 265 | + if (USE_MOCK_DATA) { | ||
| 266 | + console.log('[Index] 使用 mock 数据获取热卖产品'); | ||
| 267 | + const res = await mockHotProductsListAPI({ recommend: 'hot' }); | ||
| 268 | + if (res.code === 1 && res.data && res.data.list) { | ||
| 269 | + hotProducts.value = res.data.list; | ||
| 270 | + console.log('[Index] Mock 数据加载成功,产品数量:', res.data.list.length); | ||
| 271 | + } | ||
| 272 | + return; | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + // 生产环境:调用真实 API | ||
| 255 | const res = await listAPI({ | 276 | const res = await listAPI({ |
| 256 | recommend: 'hot' | 277 | recommend: 'hot' |
| 257 | }); | 278 | }); | ... | ... |
-
Please register or login to post a comment