feat: 产品模块接口集成完成
- 首页热卖产品集成产品列表API (listAPI, recommend=hot) - 动态标签渲染,使用API返回的bg_color和text_color - 移除硬编码数据,改用API动态返回 - 产品详情页集成详情API (detailAPI) - 产品特色改为产品描述,使用rich-text渲染富文本 - 附件大小使用file_size_formatted字段显示格式化大小 - 移除收藏功能 - 修复nut-loading不兼容问题,改用CSS加载动画 - 更新API集成日志和规范文档状态 - 添加CHANGELOG记录 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Showing
8 changed files
with
933 additions
and
239 deletions
| ... | @@ -17,6 +17,7 @@ declare module 'vue' { | ... | @@ -17,6 +17,7 @@ declare module 'vue' { |
| 17 | NutAvatar: typeof import('@nutui/nutui-taro')['Avatar'] | 17 | NutAvatar: typeof import('@nutui/nutui-taro')['Avatar'] |
| 18 | NutButton: typeof import('@nutui/nutui-taro')['Button'] | 18 | NutButton: typeof import('@nutui/nutui-taro')['Button'] |
| 19 | NutInput: typeof import('@nutui/nutui-taro')['Input'] | 19 | NutInput: typeof import('@nutui/nutui-taro')['Input'] |
| 20 | + NutLoading: typeof import('@nutui/nutui-taro')['Loading'] | ||
| 20 | NutPicker: typeof import('@nutui/nutui-taro')['Picker'] | 21 | NutPicker: typeof import('@nutui/nutui-taro')['Picker'] |
| 21 | NutPopup: typeof import('@nutui/nutui-taro')['Popup'] | 22 | NutPopup: typeof import('@nutui/nutui-taro')['Popup'] |
| 22 | NutRadio: typeof import('@nutui/nutui-taro')['Radio'] | 23 | NutRadio: typeof import('@nutui/nutui-taro')['Radio'] | ... | ... |
| ... | @@ -5,6 +5,55 @@ | ... | @@ -5,6 +5,55 @@ |
| 5 | 5 | ||
| 6 | --- | 6 | --- |
| 7 | 7 | ||
| 8 | +## [2026-02-03] - 产品模块接口集成完成 | ||
| 9 | + | ||
| 10 | +### 新增 | ||
| 11 | +- 首页热卖产品模块集成产品列表 API | ||
| 12 | + - 使用 `listAPI` 接口,参数 `recommend=hot` 获取热卖产品 | ||
| 13 | + - 移除硬编码产品数据,改用 API 动态返回的产品列表 | ||
| 14 | + - 实现动态标签样式,根据 API 返回的 `bg_color` 和 `text_color` 字段设置标签背景色和文字颜色 | ||
| 15 | + - 影响文件:src/pages/index/index.vue | ||
| 16 | + | ||
| 17 | +### 修改 | ||
| 18 | +- 产品详情页集成详情 API | ||
| 19 | + - 使用 `detailAPI` 接口获取产品详情数据 | ||
| 20 | + - "产品特色" 改为 "产品描述",使用 `<rich-text>` 组件渲染富文本内容(`product_description` 字段) | ||
| 21 | + - 附件大小直接使用 `file_size_formatted` 字段显示格式化后的文件大小 | ||
| 22 | + - 移除收藏功能(产品模块无此功能) | ||
| 23 | + - 移除 `nut-loading` 组件(Taro 不支持),改用纯 CSS 实现的加载动画 | ||
| 24 | + - 影响文件:src/pages/product-detail/index.vue | ||
| 25 | + | ||
| 26 | +### 修复 | ||
| 27 | +- 修复首页热卖产品模块重复调用 API 的问题 | ||
| 28 | +- 修复产品详情页 `nut-loading` 组件不兼容问题,使用 CSS `animate-spin` 实现加载动画 | ||
| 29 | + | ||
| 30 | +### 文档 | ||
| 31 | +- 更新 API 集成日志 `docs/api-integration-log.md` | ||
| 32 | + - 添加产品模块记录,包含产品列表和产品详情 2 个接口 | ||
| 33 | + - 更新进度统计:16 个接口(11 个已完成,3 个已废弃,2 个开发中) | ||
| 34 | + - 更新模块快速索引,添加产品模块 | ||
| 35 | +- 更新 API 规范文档状态 | ||
| 36 | + - `docs/api-specs/get_product/list.md` 状态改为 `done` | ||
| 37 | + - `docs/api-specs/get_product/detail.md` 状态改为 `done` | ||
| 38 | + | ||
| 39 | +--- | ||
| 40 | + | ||
| 41 | +**详细信息**: | ||
| 42 | +- **影响文件**: | ||
| 43 | + - `src/pages/index/index.vue`(热卖产品模块 API 集成) | ||
| 44 | + - `src/pages/product-detail/index.vue`(产品详情 API 集成) | ||
| 45 | + - `docs/api-integration-log.md`(API 集成日志更新) | ||
| 46 | + - `docs/api-specs/get_product/list.md`(状态更新) | ||
| 47 | + - `docs/api-specs/get_product/detail.md`(状态更新) | ||
| 48 | +- **技术栈**: Vue 3, Taro 4, Composition API | ||
| 49 | +- **测试状态**: ✅ 已通过 | ||
| 50 | +- **备注**: | ||
| 51 | + - 热卖产品接口参数:`recommend=hot`,无需传 limit、page、cid 参数 | ||
| 52 | + - 产品标签支持自定义背景色和文字颜色 | ||
| 53 | + - 富文本使用 Taro 的 `<rich-text>` 组件渲染 | ||
| 54 | + | ||
| 55 | +--- | ||
| 56 | + | ||
| 8 | ## [2026-02-03] - 修复反馈列表无法滚动 | 57 | ## [2026-02-03] - 修复反馈列表无法滚动 |
| 9 | 58 | ||
| 10 | ### 修复 | 59 | ### 修复 | ... | ... |
| ... | @@ -4,11 +4,11 @@ | ... | @@ -4,11 +4,11 @@ |
| 4 | 4 | ||
| 5 | ## 📊 总体进度 | 5 | ## 📊 总体进度 |
| 6 | 6 | ||
| 7 | -- **总接口数**: 14 | 7 | +- **总接口数**: 16 |
| 8 | -- **已完成**: 9 (64.3%) | 8 | +- **已完成**: 11 (68.8%) |
| 9 | - **联调中**: 0 (0%) | 9 | - **联调中**: 0 (0%) |
| 10 | -- **已废弃**: 3 (21.4%) | 10 | +- **已废弃**: 3 (18.8%) |
| 11 | -- **后端开发中**: 2 (14.3%) | 11 | +- **后端开发中**: 2 (12.5%) |
| 12 | - **有阻塞**: 0 | 12 | - **有阻塞**: 0 |
| 13 | 13 | ||
| 14 | --- | 14 | --- |
| ... | @@ -402,6 +402,95 @@ | ... | @@ -402,6 +402,95 @@ |
| 402 | 402 | ||
| 403 | --- | 403 | --- |
| 404 | 404 | ||
| 405 | +### 产品模块 | ||
| 406 | + | ||
| 407 | +#### 接口 1: 产品列表 | ||
| 408 | + | ||
| 409 | +**接口信息** | ||
| 410 | +- **接口名称**: `listAPI` | ||
| 411 | +- **接口路径**: `/srv/?a=get_product&t=list` | ||
| 412 | +- **请求方法**: GET | ||
| 413 | +- **负责页面**: `src/pages/index/index.vue` (首页热卖产品模块) | ||
| 414 | +- **负责人**: 后端团队 | ||
| 415 | + | ||
| 416 | +**接口文档更新记录** | ||
| 417 | + | ||
| 418 | +| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 | | ||
| 419 | +|------|------|---------|---------|---------| | ||
| 420 | +| 2026-02-03 | v1.0 | 初始版本 | - | [查看](docs/api-specs/get_product/list.md) | | ||
| 421 | + | ||
| 422 | +**页面调试情况** | ||
| 423 | + | ||
| 424 | +| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 | | ||
| 425 | +|------|---------|---------|---------|------| | ||
| 426 | +| 2026-02-03 | `src/pages/index/index.vue` | 联调完成 | 热卖产品列表、动态标签均正常 | ✅ 已完成 | | ||
| 427 | + | ||
| 428 | +**接口状态**: ✅ 已完成 | ||
| 429 | + | ||
| 430 | +**备注**: | ||
| 431 | +- **调用参数**: `recommend: 'hot'` (热卖产品) | ||
| 432 | +- **首页场景**: 不传 limit、page、cid 参数,使用默认值 | ||
| 433 | +- **返回数据结构**: | ||
| 434 | + - `data.list[]` - 产品列表 | ||
| 435 | + - `data.categories[]` - 分类列表 | ||
| 436 | + - `data.total` - 产品总数 | ||
| 437 | +- **产品字段**: | ||
| 438 | + - `id` - 产品ID | ||
| 439 | + - `product_name` - 产品名称 | ||
| 440 | + - `recommend` - 推荐位 (normal-普通, hot-热卖) | ||
| 441 | + - `tags[]` - 产品标签数组(包含 id、name、bg_color、text_color) | ||
| 442 | + - `cover_image` - 产品封面图 | ||
| 443 | + - `categories[]` - 产品所属分类 | ||
| 444 | +- **标签渲染**: 使用 API 返回的 `bg_color` 和 `text_color` 动态设置标签样式 | ||
| 445 | +- **实现位置**: `src/pages/index/index.vue:250-262`, `src/pages/index/index.vue:52-92` | ||
| 446 | + | ||
| 447 | +--- | ||
| 448 | + | ||
| 449 | +#### 接口 2: 产品详情 | ||
| 450 | + | ||
| 451 | +**接口信息** | ||
| 452 | +- **接口名称**: `detailAPI` | ||
| 453 | +- **接口路径**: `/srv/?a=get_product&t=detail` | ||
| 454 | +- **请求方法**: GET | ||
| 455 | +- **负责页面**: `src/pages/product-detail/index.vue` | ||
| 456 | +- **负责人**: 后端团队 | ||
| 457 | + | ||
| 458 | +**接口文档更新记录** | ||
| 459 | + | ||
| 460 | +| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 | | ||
| 461 | +|------|------|---------|---------|---------| | ||
| 462 | +| 2026-02-03 | v1.0 | 初始版本 | - | [查看](docs/api-specs/get_product/detail.md) | | ||
| 463 | + | ||
| 464 | +**页面调试情况** | ||
| 465 | + | ||
| 466 | +| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 | | ||
| 467 | +|------|---------|---------|---------|------| | ||
| 468 | +| 2026-02-03 | `src/pages/product-detail/index.vue` | nut-loading 组件报错 | 改用纯 CSS 加载动画 | ✅ 已解决 | | ||
| 469 | +| 2026-02-03 | `src/pages/product-detail/index.vue` | 联调完成 | 产品详情、富文本描述、附件列表均正常 | ✅ 已完成 | | ||
| 470 | + | ||
| 471 | +**接口状态**: ✅ 已完成 | ||
| 472 | + | ||
| 473 | +**备注**: | ||
| 474 | +- **调用参数**: `i: productId` (产品ID) | ||
| 475 | +- **返回数据结构**: | ||
| 476 | + - `product_name` - 产品名称 | ||
| 477 | + - `product_description` - 产品描述(富文本HTML) | ||
| 478 | + - `cover_image` - 产品封面图 | ||
| 479 | + - `recommend` - 推荐位 | ||
| 480 | + - `tags[]` - 产品标签数组(包含 id、name、bg_color、text_color) | ||
| 481 | + - `documents[]` - 附件列表 | ||
| 482 | + - `categories[]` - 产品所属分类 | ||
| 483 | +- **富文本渲染**: 使用 `<rich-text>` 组件渲染 `product_description` 字段 | ||
| 484 | +- **附件显示**: | ||
| 485 | + - 文件名: `doc.file_name` | ||
| 486 | + - 文件大小: `doc.file_size_formatted` (已格式化,如 "72.61 KB") | ||
| 487 | + - 文件URL: `doc.file_url` | ||
| 488 | + - 点击预览: 通过 `useFileOperation` composable 打开文档 | ||
| 489 | +- **移除功能**: 原有的收藏功能已移除(按钮和代码) | ||
| 490 | +- **实现位置**: `src/pages/product-detail/index.vue:135-162`, `src/pages/product-detail/index.vue:56-92` | ||
| 491 | + | ||
| 492 | +--- | ||
| 493 | + | ||
| 405 | ### 消息模块 | 494 | ### 消息模块 |
| 406 | 495 | ||
| 407 | #### 接口 1: 我的消息列表 | 496 | #### 接口 1: 我的消息列表 |
| ... | @@ -524,19 +613,19 @@ | ... | @@ -524,19 +613,19 @@ |
| 524 | 613 | ||
| 525 | ### 本周进度 (2026-01-27 ~ 2026-02-03) | 614 | ### 本周进度 (2026-01-27 ~ 2026-02-03) |
| 526 | 615 | ||
| 527 | -- **新增接口**: 14 | 616 | +- **新增接口**: 16 |
| 528 | -- **完成联调**: 9 | 617 | +- **完成联调**: 11 |
| 529 | - **已废弃**: 3 | 618 | - **已废弃**: 3 |
| 530 | - **联调中**: 0 | 619 | - **联调中**: 0 |
| 531 | - **后端开发中**: 2 | 620 | - **后端开发中**: 2 |
| 532 | -- **发现问题**: 5 | 621 | +- **发现问题**: 6 |
| 533 | -- **解决问题**: 5 | 622 | +- **解决问题**: 6 |
| 534 | 623 | ||
| 535 | ### 历史进度 | 624 | ### 历史进度 |
| 536 | 625 | ||
| 537 | | 周 | 完成数 | 新增数 | 废弃数 | 问题数 | | 626 | | 周 | 完成数 | 新增数 | 废弃数 | 问题数 | |
| 538 | |----|--------|--------|--------|--------| | 627 | |----|--------|--------|--------|--------| |
| 539 | -| 2026-01-27 ~ 2026-02-03 | 7 | 14 | 3 | 0 | | 628 | +| 2026-01-27 ~ 2026-02-03 | 9 | 16 | 3 | 0 | |
| 540 | 629 | ||
| 541 | --- | 630 | --- |
| 542 | 631 | ||
| ... | @@ -545,17 +634,16 @@ | ... | @@ -545,17 +634,16 @@ |
| 545 | ### 按状态查看 | 634 | ### 按状态查看 |
| 546 | - [✅ 已完成](#用户中心模块) - 6个接口 | 635 | - [✅ 已完成](#用户中心模块) - 6个接口 |
| 547 | - [✅ 已完成](#意见反馈模块) - 2个接口 | 636 | - [✅ 已完成](#意见反馈模块) - 2个接口 |
| 637 | +- [✅ 已完成](#产品模块) - 2个接口 | ||
| 548 | - [❌ 已废弃](#通用模块) - 3个接口 | 638 | - [❌ 已废弃](#通用模块) - 3个接口 |
| 549 | - [⏳ 后端开发中](#消息模块) - 2个接口 | 639 | - [⏳ 后端开发中](#消息模块) - 2个接口 |
| 550 | -- [⏳ 后端开发中](#首页模块) - 1个接口 | ||
| 551 | 640 | ||
| 552 | ### 按模块查看 | 641 | ### 按模块查看 |
| 553 | - [用户中心](#用户中心模块) - ✅ 6个已完成 | 642 | - [用户中心](#用户中心模块) - ✅ 6个已完成 |
| 554 | - [通用](#通用模块) - ❌ 3个已废弃 | 643 | - [通用](#通用模块) - ❌ 3个已废弃 |
| 555 | -- [意见反馈](#意见反馈模块) - ⏳ 2个后端开发中 | 644 | +- [意见反馈](#意见反馈模块) - ✅ 2个已完成 |
| 645 | +- [产品](#产品模块) - ✅ 2个已完成 | ||
| 556 | - [消息](#消息模块) - ⏳ 2个后端开发中 | 646 | - [消息](#消息模块) - ⏳ 2个后端开发中 |
| 557 | -- [首页](#首页模块) - ⏳ 1个后端开发中 | ||
| 558 | -- [产品详情](#产品模块) - ⏳ 未开始 | ||
| 559 | - [知识库](#知识库模块) - ⏳ 未开始 | 647 | - [知识库](#知识库模块) - ⏳ 未开始 |
| 560 | - [家办](#家办模块) - ⏳ 未开始 | 648 | - [家办](#家办模块) - ⏳ 未开始 |
| 561 | - [签单](#签单模块) - ⏳ 未开始 | 649 | - [签单](#签单模块) - ⏳ 未开始 |
| ... | @@ -592,14 +680,17 @@ | ... | @@ -592,14 +680,17 @@ |
| 592 | 680 | ||
| 593 | --- | 681 | --- |
| 594 | 682 | ||
| 595 | -**最后更新时间**: 2026-02-03 22:00 | 683 | +**最后更新时间**: 2026-02-03 23:30 |
| 596 | -**文档版本**: v1.6 | 684 | +**文档版本**: v1.7 |
| 597 | **更新内容**: | 685 | **更新内容**: |
| 598 | -- 意见反馈模块联调完成:2个接口 | 686 | +- 产品模块联调完成:2个接口 |
| 599 | - - 意见反馈列表(listAPI):✅ 已完成 | 687 | + - 产品列表(listAPI):✅ 已完成 |
| 600 | - - 提交意见反馈(addAPI):✅ 已完成 | 688 | + - 首页热卖产品模块,使用 recommend=hot 参数 |
| 689 | + - 动态标签渲染(使用 API 返回的 bg_color 和 text_color) | ||
| 690 | + - 产品详情(detailAPI):✅ 已完成 | ||
| 691 | + - 产品详情页,使用富文本渲染 product_description | ||
| 692 | + - 附件列表显示(使用 file_size_formatted 字段) | ||
| 693 | + - 移除收藏功能 | ||
| 601 | - 修复问题: | 694 | - 修复问题: |
| 602 | - - 生命周期钩子导入错误(useShow → useDidShow、onMounted 从 Vue 导入) | 695 | + - 产品详情页 nut-loading 组件报错(改用纯 CSS 加载动画) |
| 603 | - - 图片显示错误(images 改为数组格式处理) | 696 | +- 更新总体进度:16个接口(11个已完成,3个已废弃,2个后端开发中) |
| 604 | - - NutUI Loading 组件报错(改用自定义 CSS spinner) | ||
| 605 | -- 更新总体进度:14个接口(9个已完成,3个已废弃,2个后端开发中) | ... | ... |
docs/api-specs/get_product/detail.md
0 → 100644
| 1 | +# 产品详情 | ||
| 2 | + | ||
| 3 | +## OpenAPI Specification | ||
| 4 | + | ||
| 5 | +```yaml | ||
| 6 | +openapi: 3.0.1 | ||
| 7 | +info: | ||
| 8 | + title: '' | ||
| 9 | + version: 1.0.0 | ||
| 10 | +paths: | ||
| 11 | + /srv/: | ||
| 12 | + get: | ||
| 13 | + summary: 产品详情 | ||
| 14 | + deprecated: false | ||
| 15 | + description: '' | ||
| 16 | + tags: | ||
| 17 | + - 产品 | ||
| 18 | + parameters: | ||
| 19 | + - name: f | ||
| 20 | + in: query | ||
| 21 | + description: '' | ||
| 22 | + required: true | ||
| 23 | + example: manulife | ||
| 24 | + schema: | ||
| 25 | + type: string | ||
| 26 | + - name: a | ||
| 27 | + in: query | ||
| 28 | + description: '' | ||
| 29 | + required: true | ||
| 30 | + example: get_product | ||
| 31 | + schema: | ||
| 32 | + type: string | ||
| 33 | + - name: t | ||
| 34 | + in: query | ||
| 35 | + description: '' | ||
| 36 | + required: true | ||
| 37 | + example: detail | ||
| 38 | + schema: | ||
| 39 | + type: string | ||
| 40 | + - name: client_id | ||
| 41 | + in: query | ||
| 42 | + description: 主体id | ||
| 43 | + required: false | ||
| 44 | + example: '30901' | ||
| 45 | + schema: | ||
| 46 | + type: string | ||
| 47 | + - name: i | ||
| 48 | + in: query | ||
| 49 | + description: 产品id | ||
| 50 | + required: true | ||
| 51 | + example: '2769848' | ||
| 52 | + schema: | ||
| 53 | + type: string | ||
| 54 | + responses: | ||
| 55 | + '200': | ||
| 56 | + description: '' | ||
| 57 | + content: | ||
| 58 | + application/json: | ||
| 59 | + schema: | ||
| 60 | + type: object | ||
| 61 | + properties: | ||
| 62 | + code: | ||
| 63 | + type: integer | ||
| 64 | + msg: | ||
| 65 | + type: integer | ||
| 66 | + data: | ||
| 67 | + type: object | ||
| 68 | + properties: | ||
| 69 | + id: | ||
| 70 | + type: integer | ||
| 71 | + title: 产品id | ||
| 72 | + product_name: | ||
| 73 | + type: string | ||
| 74 | + title: 产品名 | ||
| 75 | + recommend: | ||
| 76 | + type: string | ||
| 77 | + title: '推荐位: normal-普通, hot-热卖' | ||
| 78 | + status: | ||
| 79 | + type: string | ||
| 80 | + created_by: | ||
| 81 | + type: integer | ||
| 82 | + created_time: | ||
| 83 | + type: string | ||
| 84 | + updated_by: | ||
| 85 | + type: integer | ||
| 86 | + updated_time: | ||
| 87 | + type: string | ||
| 88 | + form_sn: | ||
| 89 | + type: string | ||
| 90 | + title: 关联表单sn | ||
| 91 | + product_description: | ||
| 92 | + type: string | ||
| 93 | + title: 产品描述 | ||
| 94 | + categories: | ||
| 95 | + type: array | ||
| 96 | + items: | ||
| 97 | + type: object | ||
| 98 | + properties: | ||
| 99 | + id: | ||
| 100 | + type: string | ||
| 101 | + title: 分类id | ||
| 102 | + name: | ||
| 103 | + type: string | ||
| 104 | + title: 分类名称 | ||
| 105 | + x-apifox-orders: | ||
| 106 | + - id | ||
| 107 | + - name | ||
| 108 | + title: 产品所属分类 | ||
| 109 | + tags: | ||
| 110 | + type: array | ||
| 111 | + items: | ||
| 112 | + type: object | ||
| 113 | + properties: | ||
| 114 | + id: | ||
| 115 | + type: string | ||
| 116 | + title: 标签id | ||
| 117 | + name: | ||
| 118 | + type: string | ||
| 119 | + title: 标签名 | ||
| 120 | + bg_color: | ||
| 121 | + type: string | ||
| 122 | + title: 标签背景色 | ||
| 123 | + text_color: | ||
| 124 | + type: string | ||
| 125 | + title: 标签文字色 | ||
| 126 | + required: | ||
| 127 | + - id | ||
| 128 | + - name | ||
| 129 | + - bg_color | ||
| 130 | + - text_color | ||
| 131 | + x-apifox-orders: | ||
| 132 | + - id | ||
| 133 | + - name | ||
| 134 | + - bg_color | ||
| 135 | + - text_color | ||
| 136 | + title: 产品标签 | ||
| 137 | + documents: | ||
| 138 | + type: array | ||
| 139 | + items: | ||
| 140 | + type: object | ||
| 141 | + properties: | ||
| 142 | + file_url: | ||
| 143 | + type: string | ||
| 144 | + title: 附件地址 | ||
| 145 | + file_name: | ||
| 146 | + type: string | ||
| 147 | + title: 附件名 | ||
| 148 | + file_size: | ||
| 149 | + type: string | ||
| 150 | + title: 附件大小 | ||
| 151 | + file_size_formatted: | ||
| 152 | + type: string | ||
| 153 | + title: 附件大小(转换过显示) | ||
| 154 | + x-apifox-orders: | ||
| 155 | + - file_url | ||
| 156 | + - file_name | ||
| 157 | + - file_size | ||
| 158 | + - file_size_formatted | ||
| 159 | + title: 附件列表 | ||
| 160 | + cover_image: | ||
| 161 | + type: string | ||
| 162 | + title: 产品封面图 | ||
| 163 | + required: | ||
| 164 | + - id | ||
| 165 | + - product_name | ||
| 166 | + - recommend | ||
| 167 | + - status | ||
| 168 | + - created_by | ||
| 169 | + - created_time | ||
| 170 | + - updated_by | ||
| 171 | + - updated_time | ||
| 172 | + - form_sn | ||
| 173 | + - product_description | ||
| 174 | + - categories | ||
| 175 | + - tags | ||
| 176 | + - documents | ||
| 177 | + - cover_image | ||
| 178 | + x-apifox-orders: | ||
| 179 | + - id | ||
| 180 | + - product_name | ||
| 181 | + - recommend | ||
| 182 | + - status | ||
| 183 | + - created_by | ||
| 184 | + - created_time | ||
| 185 | + - updated_by | ||
| 186 | + - updated_time | ||
| 187 | + - form_sn | ||
| 188 | + - product_description | ||
| 189 | + - cover_image | ||
| 190 | + - categories | ||
| 191 | + - tags | ||
| 192 | + - documents | ||
| 193 | + required: | ||
| 194 | + - code | ||
| 195 | + - msg | ||
| 196 | + - data | ||
| 197 | + x-apifox-orders: | ||
| 198 | + - code | ||
| 199 | + - msg | ||
| 200 | + - data | ||
| 201 | + example: | ||
| 202 | + code: 1 | ||
| 203 | + msg: 0 | ||
| 204 | + data: | ||
| 205 | + id: 2769848 | ||
| 206 | + product_name: '1111' | ||
| 207 | + recommend: normal | ||
| 208 | + sort: 0 | ||
| 209 | + status: '3' | ||
| 210 | + created_by: 21580 | ||
| 211 | + created_time: '2026-02-02 16:33:01' | ||
| 212 | + updated_by: 21580 | ||
| 213 | + updated_time: '2026-02-03 14:52:41' | ||
| 214 | + client_id: 30901 | ||
| 215 | + form_sn: customize_jsj_ivleuz | ||
| 216 | + product_description: "<p>5564</p>\r\n<p>hdye</p>" | ||
| 217 | + categories: | ||
| 218 | + - id: '2769851' | ||
| 219 | + name: '11' | ||
| 220 | + tags: | ||
| 221 | + - id: '2769846' | ||
| 222 | + name: 测试1 | ||
| 223 | + bg_color: '#1e9fff' | ||
| 224 | + text_color: '#ffffff' | ||
| 225 | + - id: '2769847' | ||
| 226 | + name: '111' | ||
| 227 | + bg_color: '#3e5160' | ||
| 228 | + text_color: '#ffffff' | ||
| 229 | + documents: | ||
| 230 | + - file_url: >- | ||
| 231 | + https://cdn.ipadbiz.cn/space_30901/申请提交-生成计划书_FvdRVOS0K-Wmp05ZKHpx64sEXcKQ.png | ||
| 232 | + file_name: 申请提交-生成计划书.png | ||
| 233 | + file_size: '74356' | ||
| 234 | + file_size_formatted: 72.61 KB | ||
| 235 | + headers: {} | ||
| 236 | + x-apifox-name: 成功 | ||
| 237 | + x-apifox-ordering: 0 | ||
| 238 | + security: [] | ||
| 239 | + x-apifox-folder: 产品 | ||
| 240 | + x-apifox-status: done | ||
| 241 | + x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-414567246-run | ||
| 242 | +components: | ||
| 243 | + schemas: {} | ||
| 244 | + responses: {} | ||
| 245 | + securitySchemes: {} | ||
| 246 | +servers: [] | ||
| 247 | +security: [] | ||
| 248 | + | ||
| 249 | +``` |
docs/api-specs/get_product/list.md
0 → 100644
| 1 | +# 产品列表 | ||
| 2 | + | ||
| 3 | +## OpenAPI Specification | ||
| 4 | + | ||
| 5 | +```yaml | ||
| 6 | +openapi: 3.0.1 | ||
| 7 | +info: | ||
| 8 | + title: '' | ||
| 9 | + version: 1.0.0 | ||
| 10 | +paths: | ||
| 11 | + /srv/: | ||
| 12 | + get: | ||
| 13 | + summary: 产品列表 | ||
| 14 | + deprecated: false | ||
| 15 | + description: '' | ||
| 16 | + tags: | ||
| 17 | + - 产品 | ||
| 18 | + parameters: | ||
| 19 | + - name: f | ||
| 20 | + in: query | ||
| 21 | + description: '' | ||
| 22 | + required: true | ||
| 23 | + example: manulife | ||
| 24 | + schema: | ||
| 25 | + type: string | ||
| 26 | + - name: a | ||
| 27 | + in: query | ||
| 28 | + description: '' | ||
| 29 | + required: true | ||
| 30 | + example: get_product | ||
| 31 | + schema: | ||
| 32 | + type: string | ||
| 33 | + - name: t | ||
| 34 | + in: query | ||
| 35 | + description: '' | ||
| 36 | + required: true | ||
| 37 | + example: list | ||
| 38 | + schema: | ||
| 39 | + type: string | ||
| 40 | + - name: client_id | ||
| 41 | + in: query | ||
| 42 | + description: 主体id | ||
| 43 | + required: false | ||
| 44 | + example: '30901' | ||
| 45 | + schema: | ||
| 46 | + type: string | ||
| 47 | + - name: limit | ||
| 48 | + in: query | ||
| 49 | + description: '' | ||
| 50 | + required: false | ||
| 51 | + example: '10' | ||
| 52 | + schema: | ||
| 53 | + type: string | ||
| 54 | + - name: page | ||
| 55 | + in: query | ||
| 56 | + description: '' | ||
| 57 | + required: false | ||
| 58 | + example: '0' | ||
| 59 | + schema: | ||
| 60 | + type: string | ||
| 61 | + - name: cid | ||
| 62 | + in: query | ||
| 63 | + description: 分类id | ||
| 64 | + required: false | ||
| 65 | + schema: | ||
| 66 | + type: string | ||
| 67 | + - name: recommend | ||
| 68 | + in: query | ||
| 69 | + description: '推荐位: normal-普通, hot-热卖' | ||
| 70 | + required: false | ||
| 71 | + schema: | ||
| 72 | + type: string | ||
| 73 | + responses: | ||
| 74 | + '200': | ||
| 75 | + description: '' | ||
| 76 | + content: | ||
| 77 | + application/json: | ||
| 78 | + schema: | ||
| 79 | + type: object | ||
| 80 | + properties: | ||
| 81 | + code: | ||
| 82 | + type: integer | ||
| 83 | + msg: | ||
| 84 | + type: integer | ||
| 85 | + data: | ||
| 86 | + type: object | ||
| 87 | + properties: | ||
| 88 | + categories: | ||
| 89 | + type: array | ||
| 90 | + items: | ||
| 91 | + type: object | ||
| 92 | + properties: | ||
| 93 | + id: | ||
| 94 | + type: integer | ||
| 95 | + title: 分类id | ||
| 96 | + name: | ||
| 97 | + type: string | ||
| 98 | + title: 分类名 | ||
| 99 | + x-apifox-orders: | ||
| 100 | + - id | ||
| 101 | + - name | ||
| 102 | + title: 分类列表 | ||
| 103 | + list: | ||
| 104 | + type: array | ||
| 105 | + items: | ||
| 106 | + type: object | ||
| 107 | + properties: | ||
| 108 | + id: | ||
| 109 | + type: integer | ||
| 110 | + title: 产品id | ||
| 111 | + product_name: | ||
| 112 | + type: string | ||
| 113 | + title: 产品名 | ||
| 114 | + recommend: | ||
| 115 | + type: string | ||
| 116 | + title: '推荐位: normal-普通, hot-热卖' | ||
| 117 | + form_sn: | ||
| 118 | + type: string | ||
| 119 | + created_time: | ||
| 120 | + type: string | ||
| 121 | + title: 创建时间 | ||
| 122 | + categories: | ||
| 123 | + type: array | ||
| 124 | + items: | ||
| 125 | + type: object | ||
| 126 | + properties: | ||
| 127 | + id: | ||
| 128 | + type: string | ||
| 129 | + title: 分类id | ||
| 130 | + name: | ||
| 131 | + type: string | ||
| 132 | + title: 分类名 | ||
| 133 | + required: | ||
| 134 | + - id | ||
| 135 | + - name | ||
| 136 | + x-apifox-orders: | ||
| 137 | + - id | ||
| 138 | + - name | ||
| 139 | + title: 产品所属分类 | ||
| 140 | + tags: | ||
| 141 | + type: array | ||
| 142 | + items: | ||
| 143 | + type: object | ||
| 144 | + properties: | ||
| 145 | + id: | ||
| 146 | + type: string | ||
| 147 | + title: 标签id | ||
| 148 | + name: | ||
| 149 | + type: string | ||
| 150 | + title: 标签名 | ||
| 151 | + bg_color: | ||
| 152 | + type: string | ||
| 153 | + title: 标签背景色 | ||
| 154 | + text_color: | ||
| 155 | + type: string | ||
| 156 | + title: 标签文字色 | ||
| 157 | + required: | ||
| 158 | + - id | ||
| 159 | + - name | ||
| 160 | + - bg_color | ||
| 161 | + - text_color | ||
| 162 | + x-apifox-orders: | ||
| 163 | + - id | ||
| 164 | + - name | ||
| 165 | + - bg_color | ||
| 166 | + - text_color | ||
| 167 | + title: 产品标签 | ||
| 168 | + cover_image: | ||
| 169 | + type: string | ||
| 170 | + title: 产品封面图 | ||
| 171 | + required: | ||
| 172 | + - id | ||
| 173 | + - product_name | ||
| 174 | + - recommend | ||
| 175 | + - form_sn | ||
| 176 | + - created_time | ||
| 177 | + - categories | ||
| 178 | + - tags | ||
| 179 | + - cover_image | ||
| 180 | + x-apifox-orders: | ||
| 181 | + - id | ||
| 182 | + - product_name | ||
| 183 | + - recommend | ||
| 184 | + - form_sn | ||
| 185 | + - cover_image | ||
| 186 | + - created_time | ||
| 187 | + - categories | ||
| 188 | + - tags | ||
| 189 | + title: 产品列表 | ||
| 190 | + total: | ||
| 191 | + type: integer | ||
| 192 | + title: 产品总数 | ||
| 193 | + required: | ||
| 194 | + - categories | ||
| 195 | + - list | ||
| 196 | + - total | ||
| 197 | + x-apifox-orders: | ||
| 198 | + - categories | ||
| 199 | + - list | ||
| 200 | + - total | ||
| 201 | + required: | ||
| 202 | + - code | ||
| 203 | + - msg | ||
| 204 | + - data | ||
| 205 | + x-apifox-orders: | ||
| 206 | + - code | ||
| 207 | + - msg | ||
| 208 | + - data | ||
| 209 | + example: | ||
| 210 | + code: 1 | ||
| 211 | + msg: 0 | ||
| 212 | + data: | ||
| 213 | + categories: | ||
| 214 | + - id: 2769851 | ||
| 215 | + name: '11' | ||
| 216 | + list: | ||
| 217 | + - id: 2769856 | ||
| 218 | + product_name: '22' | ||
| 219 | + recommend: hot | ||
| 220 | + form_sn: customize_jsj_pnzuky | ||
| 221 | + created_time: '2026-02-03 10:36:29' | ||
| 222 | + categories: | ||
| 223 | + - id: '2769851' | ||
| 224 | + name: '11' | ||
| 225 | + tags: | ||
| 226 | + - id: '2769847' | ||
| 227 | + name: '111' | ||
| 228 | + bg_color: '#3e5160' | ||
| 229 | + text_color: '#ffffff' | ||
| 230 | + - id: 2769848 | ||
| 231 | + product_name: '1111' | ||
| 232 | + recommend: normal | ||
| 233 | + form_sn: customize_jsj_ivleuz | ||
| 234 | + created_time: '2026-02-02 16:33:01' | ||
| 235 | + categories: | ||
| 236 | + - id: '2769851' | ||
| 237 | + name: '11' | ||
| 238 | + tags: | ||
| 239 | + - id: '2769846' | ||
| 240 | + name: 测试1 | ||
| 241 | + bg_color: '#1e9fff' | ||
| 242 | + text_color: '#ffffff' | ||
| 243 | + - id: '2769847' | ||
| 244 | + name: '111' | ||
| 245 | + bg_color: '#3e5160' | ||
| 246 | + text_color: '#ffffff' | ||
| 247 | + - id: 2769845 | ||
| 248 | + product_name: '1' | ||
| 249 | + recommend: normal | ||
| 250 | + form_sn: customize_jsj_pnzuky | ||
| 251 | + created_time: '2026-02-02 16:22:26' | ||
| 252 | + categories: [] | ||
| 253 | + tags: [] | ||
| 254 | + total: 3 | ||
| 255 | + headers: {} | ||
| 256 | + x-apifox-name: 成功 | ||
| 257 | + x-apifox-ordering: 0 | ||
| 258 | + security: [] | ||
| 259 | + x-apifox-folder: 产品 | ||
| 260 | + x-apifox-status: done | ||
| 261 | + x-run-in-apifox: https://app.apifox.com/web/project/7792797/apis/api-414404531-run | ||
| 262 | +components: | ||
| 263 | + schemas: {} | ||
| 264 | + responses: {} | ||
| 265 | + securitySchemes: {} | ||
| 266 | +servers: [] | ||
| 267 | +security: [] | ||
| 268 | + | ||
| 269 | +``` |
src/api/get_product.js
0 → 100644
| 1 | +import { fn, fetch } from '@/api/fn'; | ||
| 2 | + | ||
| 3 | +const Api = { | ||
| 4 | + Detail: '/srv/?a=get_product&t=detail', | ||
| 5 | + List: '/srv/?a=get_product&t=list', | ||
| 6 | +} | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * @description 产品详情 | ||
| 10 | + * @remark | ||
| 11 | + * @param {Object} params 请求参数 | ||
| 12 | + * @param {string} params.client_id (可选) 主体id | ||
| 13 | + * @param {string} params.i 产品id | ||
| 14 | + * @returns {Promise<{ | ||
| 15 | + * code: number; // 状态码 | ||
| 16 | + * msg: string; // 消息 | ||
| 17 | + * data: { | ||
| 18 | + * id: integer; // 产品id | ||
| 19 | + * product_name: string; // 产品名 | ||
| 20 | + * recommend: string; // 推荐位: normal-普通, hot-热卖 | ||
| 21 | + * status: string; // | ||
| 22 | + * created_by: integer; // | ||
| 23 | + * created_time: string; // | ||
| 24 | + * updated_by: integer; // | ||
| 25 | + * updated_time: string; // | ||
| 26 | + * form_sn: string; // 关联表单sn | ||
| 27 | + * product_description: string; // 产品描述 | ||
| 28 | + * categories: Array<{ | ||
| 29 | + * id: string; // 分类id | ||
| 30 | + * name: string; // 分类名称 | ||
| 31 | + * }>; | ||
| 32 | + * tags: Array<{ | ||
| 33 | + * id: string; // 标签id | ||
| 34 | + * name: string; // 标签名 | ||
| 35 | + * bg_color: string; // 标签背景色 | ||
| 36 | + * text_color: string; // 标签文字色 | ||
| 37 | + * }>; | ||
| 38 | + * documents: Array<{ | ||
| 39 | + * file_url: string; // 附件地址 | ||
| 40 | + * file_name: string; // 附件名 | ||
| 41 | + * file_size: string; // 附件大小 | ||
| 42 | + * file_size_formatted: string; // 附件大小(转换过显示) | ||
| 43 | + * }>; | ||
| 44 | + * cover_image: string; // 产品封面图 | ||
| 45 | + * }; | ||
| 46 | + * }>} | ||
| 47 | + */ | ||
| 48 | +export const detailAPI = (params) => fn(fetch.get(Api.Detail, params)); | ||
| 49 | + | ||
| 50 | +/** | ||
| 51 | + * @description 产品列表 | ||
| 52 | + * @remark | ||
| 53 | + * @param {Object} params 请求参数 | ||
| 54 | + * @param {string} params.client_id (可选) 主体id | ||
| 55 | + * @param {string} params.limit (可选) | ||
| 56 | + * @param {string} params.page (可选) | ||
| 57 | + * @param {string} params.cid (可选) 分类id | ||
| 58 | + * @param {string} params.recommend (可选) 推荐位: normal-普通, hot-热卖 | ||
| 59 | + * @returns {Promise<{ | ||
| 60 | + * code: number; // 状态码 | ||
| 61 | + * msg: string; // 消息 | ||
| 62 | + * data: { | ||
| 63 | + * categories: Array<{ | ||
| 64 | + * id: integer; // 分类id | ||
| 65 | + * name: string; // 分类名 | ||
| 66 | + * }>; | ||
| 67 | + * list: Array<{ | ||
| 68 | + * id: integer; // 产品id | ||
| 69 | + * product_name: string; // 产品名 | ||
| 70 | + * recommend: string; // 推荐位: normal-普通, hot-热卖 | ||
| 71 | + * form_sn: string; // | ||
| 72 | + * created_time: string; // 创建时间 | ||
| 73 | + * categories: array; // 产品所属分类 | ||
| 74 | + * tags: array; // 产品标签 | ||
| 75 | + * cover_image: string; // 产品封面图 | ||
| 76 | + * }>; | ||
| 77 | + * total: integer; // 产品总数 | ||
| 78 | + * }; | ||
| 79 | + * }>} | ||
| 80 | + */ | ||
| 81 | +export const listAPI = (params) => fn(fetch.get(Api.List, params)); |
| ... | @@ -26,14 +26,14 @@ | ... | @@ -26,14 +26,14 @@ |
| 26 | <view class="flex flex-wrap"> | 26 | <view class="flex flex-wrap"> |
| 27 | <view | 27 | <view |
| 28 | class="flex flex-col items-center w-1/3 mb-[40rpx]" | 28 | class="flex flex-col items-center w-1/3 mb-[40rpx]" |
| 29 | - v-for="(item, index) in loopData0" | 29 | + v-for="(item, index) in loopNav" |
| 30 | :key="index" | 30 | :key="index" |
| 31 | @tap="handleGridNav(item)" | 31 | @tap="handleGridNav(item)" |
| 32 | > | 32 | > |
| 33 | <view class="w-[88rpx] h-[88rpx] rounded-[24rpx] bg-blue-50 flex items-center justify-center mb-[16rpx]"> | 33 | <view class="w-[88rpx] h-[88rpx] rounded-[24rpx] bg-blue-50 flex items-center justify-center mb-[16rpx]"> |
| 34 | <IconFont :name="item.icon" class="text-blue-600" size="24" /> | 34 | <IconFont :name="item.icon" class="text-blue-600" size="24" /> |
| 35 | </view> | 35 | </view> |
| 36 | - <text class="text-gray-800 text-[26rpx]">{{ item.lanhutext0 }}</text> | 36 | + <text class="text-gray-800 text-[26rpx]">{{ item.name }}</text> |
| 37 | </view> | 37 | </view> |
| 38 | </view> | 38 | </view> |
| 39 | </view> | 39 | </view> |
| ... | @@ -48,66 +48,43 @@ | ... | @@ -48,66 +48,43 @@ |
| 48 | </view> | 48 | </view> |
| 49 | </view> | 49 | </view> |
| 50 | 50 | ||
| 51 | - <!-- Product Card 1 --> | 51 | + <!-- 动态产品列表 --> |
| 52 | - <view class="bg-gray-50 rounded-[24rpx] p-[28rpx] mb-[24rpx]"> | 52 | + <view |
| 53 | - <text class="block text-gray-800 text-[28rpx] font-medium mb-[20rpx]">家庭财富传承保障计划(分红)</text> | 53 | + v-for="(product, index) in hotProducts" |
| 54 | - <view class="flex flex-wrap gap-[12rpx] mb-[24rpx]"> | 54 | + :key="product.id" |
| 55 | - <view class="bg-red-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | 55 | + class="bg-gray-50 rounded-[24rpx] p-[28rpx]" |
| 56 | - <text class="text-red-600 text-[22rpx]">收益率3.5%</text> | 56 | + :class="{ 'mb-[24rpx]': index < hotProducts.length - 1 }" |
| 57 | - </view> | ||
| 58 | - <view class="bg-orange-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | ||
| 59 | - <text class="text-orange-600 text-[22rpx]">5年超值</text> | ||
| 60 | - </view> | ||
| 61 | - <view class="bg-green-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | ||
| 62 | - <text class="text-green-600 text-[22rpx]">保证收益万能</text> | ||
| 63 | - </view> | ||
| 64 | - </view> | ||
| 65 | - <view class="flex justify-between gap-[24rpx]"> | ||
| 66 | - <nut-button | ||
| 67 | - plain | ||
| 68 | - color="#2563EB" | ||
| 69 | - class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0 !border-blue-600" | ||
| 70 | - @tap="goToProductDetail(1)" | ||
| 71 | > | 57 | > |
| 72 | - 产品详情 | 58 | + <text class="block text-gray-800 text-[28rpx] font-medium mb-[20rpx]">{{ product.product_name }}</text> |
| 73 | - </nut-button> | 59 | + |
| 74 | - <nut-button | 60 | + <!-- 动态标签 --> |
| 75 | - color="#2563EB" | 61 | + <view v-if="product.tags && product.tags.length" class="flex flex-wrap gap-[12rpx] mb-[24rpx]"> |
| 76 | - class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0" | 62 | + <view |
| 77 | - @tap="openPlanPopup('A')" | 63 | + v-for="tag in product.tags" |
| 64 | + :key="tag.id" | ||
| 65 | + class="rounded-[8rpx] px-[16rpx] py-[6rpx]" | ||
| 66 | + :style="{ | ||
| 67 | + backgroundColor: tag.bg_color, | ||
| 68 | + color: tag.text_color | ||
| 69 | + }" | ||
| 78 | > | 70 | > |
| 79 | - 计划书 | 71 | + <text class="text-[22rpx]">{{ tag.name }}</text> |
| 80 | - </nut-button> | ||
| 81 | </view> | 72 | </view> |
| 82 | </view> | 73 | </view> |
| 83 | 74 | ||
| 84 | - <!-- Product Card 2 --> | ||
| 85 | - <view class="bg-gray-50 rounded-[24rpx] p-[28rpx]"> | ||
| 86 | - <text class="block text-gray-800 text-[28rpx] font-medium mb-[20rpx]">儿童教育金储备方案(分红)</text> | ||
| 87 | - <view class="flex flex-wrap gap-[12rpx] mb-[24rpx]"> | ||
| 88 | - <view class="bg-red-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | ||
| 89 | - <text class="text-red-600 text-[22rpx]">收益率4.2%</text> | ||
| 90 | - </view> | ||
| 91 | - <view class="bg-orange-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | ||
| 92 | - <text class="text-orange-600 text-[22rpx]">10年期</text> | ||
| 93 | - </view> | ||
| 94 | - <view class="bg-green-50 rounded-[8rpx] px-[16rpx] py-[6rpx]"> | ||
| 95 | - <text class="text-green-600 text-[22rpx]">教育专属</text> | ||
| 96 | - </view> | ||
| 97 | - </view> | ||
| 98 | <view class="flex justify-between gap-[24rpx]"> | 75 | <view class="flex justify-between gap-[24rpx]"> |
| 99 | <nut-button | 76 | <nut-button |
| 100 | plain | 77 | plain |
| 101 | color="#2563EB" | 78 | color="#2563EB" |
| 102 | class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0 !border-blue-600" | 79 | class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0 !border-blue-600" |
| 103 | - @tap="goToProductDetail(2)" | 80 | + @tap="goToProductDetail(product.id)" |
| 104 | > | 81 | > |
| 105 | - 产品资料 | 82 | + 产品详情 |
| 106 | </nut-button> | 83 | </nut-button> |
| 107 | <nut-button | 84 | <nut-button |
| 108 | color="#2563EB" | 85 | color="#2563EB" |
| 109 | class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0" | 86 | class="flex-1 !h-[64rpx] !rounded-[16rpx] !text-[26rpx] !m-0" |
| 110 | - @tap="openPlanPopup('B')" | 87 | + @tap="openPlanPopup(product.id)" |
| 111 | > | 88 | > |
| 112 | 计划书 | 89 | 计划书 |
| 113 | </nut-button> | 90 | </nut-button> |
| ... | @@ -187,7 +164,7 @@ | ... | @@ -187,7 +164,7 @@ |
| 187 | 164 | ||
| 188 | <script setup> | 165 | <script setup> |
| 189 | import { ref, shallowRef } from 'vue'; | 166 | import { ref, shallowRef } from 'vue'; |
| 190 | -import Taro, { useShareAppMessage } from '@tarojs/taro'; | 167 | +import Taro, { useShareAppMessage, useLoad } from '@tarojs/taro'; |
| 191 | import { useGo } from '@/hooks/useGo'; | 168 | import { useGo } from '@/hooks/useGo'; |
| 192 | import { useListItemClick, ListType } from '@/composables/useListItemClick'; | 169 | import { useListItemClick, ListType } from '@/composables/useListItemClick'; |
| 193 | import { getDocumentIcon, getDocumentLabel } from '@/utils/documentIcons'; | 170 | import { getDocumentIcon, getDocumentLabel } from '@/utils/documentIcons'; |
| ... | @@ -197,6 +174,7 @@ import PlanPopup from '@/components/PlanPopup/index.vue'; | ... | @@ -197,6 +174,7 @@ import PlanPopup from '@/components/PlanPopup/index.vue'; |
| 197 | import SchemeA from '@/components/PlanSchemes/SchemeA.vue'; | 174 | import SchemeA from '@/components/PlanSchemes/SchemeA.vue'; |
| 198 | import SchemeB from '@/components/PlanSchemes/SchemeB.vue'; | 175 | import SchemeB from '@/components/PlanSchemes/SchemeB.vue'; |
| 199 | import ListItemActions from '@/components/ListItemActions/index.vue'; | 176 | import ListItemActions from '@/components/ListItemActions/index.vue'; |
| 177 | +import { listAPI } from '@/api/get_product'; | ||
| 200 | 178 | ||
| 201 | // Plan Popup State | 179 | // Plan Popup State |
| 202 | const showPlanPopup = ref(false); | 180 | const showPlanPopup = ref(false); |
| ... | @@ -226,16 +204,42 @@ const handlePlanSubmit = (formData) => { | ... | @@ -226,16 +204,42 @@ const handlePlanSubmit = (formData) => { |
| 226 | }; | 204 | }; |
| 227 | 205 | ||
| 228 | // Grid navigation data with routes | 206 | // Grid navigation data with routes |
| 229 | -const loopData0 = shallowRef([ | 207 | +const loopNav = shallowRef([ |
| 230 | - { icon: 'order', lanhutext0: '计划书', route: '/pages/plan/index' }, | 208 | + { icon: 'order', name: '计划书', route: '/pages/plan/index' }, |
| 231 | - { icon: 'my', lanhutext0: '入职相关', route: '/pages/onboarding/index' }, | 209 | + { icon: 'my', name: '入职相关', route: '/pages/onboarding/index' }, |
| 232 | - { icon: 'cart', lanhutext0: '签单相关', route: '/pages/signing/index' }, | 210 | + { icon: 'cart', name: '签单相关', route: '/pages/signing/index' }, |
| 233 | - { icon: 'home', lanhutext0: '家办相关', route: '/pages/family-office/index' }, | 211 | + { icon: 'home', name: '家办相关', route: '/pages/family-office/index' }, |
| 234 | - { icon: 'category', lanhutext0: '产品知识库', route: '/pages/knowledge-base/index' }, | 212 | + { icon: 'category', name: '产品知识库', route: '/pages/knowledge-base/index' }, |
| 235 | - { icon: 'star', lanhutext0: '工具箱', route: null }, // 待开发 | 213 | + { icon: 'star', name: '工具箱', route: null }, // 待开发 |
| 236 | ]); | 214 | ]); |
| 237 | 215 | ||
| 238 | /** | 216 | /** |
| 217 | + * 热卖产品数据 | ||
| 218 | + * | ||
| 219 | + * @description 从服务器获取的热卖产品列表 | ||
| 220 | + */ | ||
| 221 | +const hotProducts = ref([]); | ||
| 222 | + | ||
| 223 | +/** | ||
| 224 | + * 获取热卖产品列表 | ||
| 225 | + * | ||
| 226 | + * @description 调用产品列表API,recommend参数为hot | ||
| 227 | + */ | ||
| 228 | +const fetchHotProducts = async () => { | ||
| 229 | + try { | ||
| 230 | + const res = await listAPI({ | ||
| 231 | + recommend: 'hot' | ||
| 232 | + }); | ||
| 233 | + | ||
| 234 | + if (res.code === 1 && res.data && res.data.list) { | ||
| 235 | + hotProducts.value = res.data.list; | ||
| 236 | + } | ||
| 237 | + } catch (err) { | ||
| 238 | + console.error('获取热卖产品失败:', err); | ||
| 239 | + } | ||
| 240 | +}; | ||
| 241 | + | ||
| 242 | +/** | ||
| 239 | * 热门资料数据 | 243 | * 热门资料数据 |
| 240 | * | 244 | * |
| 241 | * @description 本周热门资料列表数据,包含不同类型的文件 | 245 | * @description 本周热门资料列表数据,包含不同类型的文件 |
| ... | @@ -328,6 +332,11 @@ const openWebView = (url) => { | ... | @@ -328,6 +332,11 @@ const openWebView = (url) => { |
| 328 | }); | 332 | }); |
| 329 | }; | 333 | }; |
| 330 | 334 | ||
| 335 | +// 页面加载时获取热卖产品 | ||
| 336 | +useLoad(() => { | ||
| 337 | + fetchHotProducts(); | ||
| 338 | +}); | ||
| 339 | + | ||
| 331 | useShareAppMessage(() => { | 340 | useShareAppMessage(() => { |
| 332 | return { | 341 | return { |
| 333 | title: '臻奇智荟圈', | 342 | title: '臻奇智荟圈', | ... | ... |
| ... | @@ -6,16 +6,29 @@ | ... | @@ -6,16 +6,29 @@ |
| 6 | <div class="min-h-screen bg-[#F9FAFB] pb-[calc(160rpx+env(safe-area-inset-bottom))]"> | 6 | <div class="min-h-screen bg-[#F9FAFB] pb-[calc(160rpx+env(safe-area-inset-bottom))]"> |
| 7 | <NavHeader title="产品详情" /> | 7 | <NavHeader title="产品详情" /> |
| 8 | 8 | ||
| 9 | + <!-- Loading State --> | ||
| 10 | + <div v-if="loading" class="flex items-center justify-center h-screen"> | ||
| 11 | + <div class="flex flex-col items-center"> | ||
| 12 | + <div class="w-[64rpx] h-[64rpx] border-4 border-gray-200 border-t-blue-600 rounded-full animate-spin mb-[24rpx]"></div> | ||
| 13 | + <text class="text-gray-600 text-[28rpx]">加载中...</text> | ||
| 14 | + </div> | ||
| 15 | + </div> | ||
| 16 | + | ||
| 17 | + <!-- Content --> | ||
| 18 | + <div v-else> | ||
| 9 | <!-- Banner Image --> | 19 | <!-- Banner Image --> |
| 10 | <div class="w-full h-[420rpx] relative"> | 20 | <div class="w-full h-[420rpx] relative"> |
| 11 | <img | 21 | <img |
| 12 | class="w-full h-full object-cover" | 22 | class="w-full h-full object-cover" |
| 13 | - :src="bannerImage" | 23 | + :src="productDetail.cover_image || bannerImage" |
| 14 | mode="aspectFill" | 24 | mode="aspectFill" |
| 15 | /> | 25 | /> |
| 16 | <div class="absolute top-[32rpx] right-[32rpx] flex items-center gap-[16rpx]"> | 26 | <div class="absolute top-[32rpx] right-[32rpx] flex items-center gap-[16rpx]"> |
| 17 | <!-- Hot Tag --> | 27 | <!-- Hot Tag --> |
| 18 | - <div class="bg-red-500 text-white text-[24rpx] px-[20rpx] py-[10rpx] rounded-full shadow-sm backdrop-blur-sm bg-opacity-90"> | 28 | + <div |
| 29 | + v-if="productDetail.recommend === 'hot'" | ||
| 30 | + class="bg-red-500 text-white text-[24rpx] px-[20rpx] py-[10rpx] rounded-full shadow-sm backdrop-blur-sm bg-opacity-90" | ||
| 31 | + > | ||
| 19 | 热卖 | 32 | 热卖 |
| 20 | </div> | 33 | </div> |
| 21 | </div> | 34 | </div> |
| ... | @@ -23,89 +36,59 @@ | ... | @@ -23,89 +36,59 @@ |
| 23 | 36 | ||
| 24 | <!-- Product Header --> | 37 | <!-- Product Header --> |
| 25 | <div class="relative mt-[-40rpx] bg-white rounded-t-[40rpx] px-[40rpx] pt-[48rpx] pb-[40rpx] z-10"> | 38 | <div class="relative mt-[-40rpx] bg-white rounded-t-[40rpx] px-[40rpx] pt-[48rpx] pb-[40rpx] z-10"> |
| 26 | - <div class="flex items-start justify-between mb-[24rpx]"> | 39 | + <h1 class="text-[#1F2937] text-[44rpx] font-bold leading-[1.2] mb-[24rpx]"> |
| 27 | - <h1 class="text-[#1F2937] text-[44rpx] font-bold flex-1 mr-[24rpx] leading-[1.2]">终身寿险尊享版</h1> | 40 | + {{ productDetail.product_name || '产品详情' }} |
| 28 | - <!-- Favorite Button --> | 41 | + </h1> |
| 29 | - <div | ||
| 30 | - class="w-[72rpx] h-[72rpx] flex-shrink-0 flex items-center justify-center rounded-full bg-gray-50 active:scale-95 transition-transform" | ||
| 31 | - @tap="toggleCollect" | ||
| 32 | - > | ||
| 33 | - <IconFont | ||
| 34 | - :name="isCollected ? 'heart-fill' : 'heart'" | ||
| 35 | - size="24" | ||
| 36 | - :color="isCollected ? '#EF4444' : '#9CA3AF'" | ||
| 37 | - /> | ||
| 38 | - </div> | ||
| 39 | - </div> | ||
| 40 | - | ||
| 41 | - <div class="flex flex-wrap gap-[16rpx]"> | ||
| 42 | - <div class="px-[16rpx] py-[6rpx] bg-red-50 rounded-[8rpx]"> | ||
| 43 | - <span class="text-red-600 text-[24rpx]">收益率3.5%</span> | ||
| 44 | - </div> | ||
| 45 | - <div class="px-[16rpx] py-[6rpx] bg-orange-50 rounded-[8rpx]"> | ||
| 46 | - <span class="text-orange-600 text-[24rpx]">5年超值</span> | ||
| 47 | - </div> | ||
| 48 | - <div class="px-[16rpx] py-[6rpx] bg-green-50 rounded-[8rpx]"> | ||
| 49 | - <span class="text-green-600 text-[24rpx]">保证收益万能</span> | ||
| 50 | - </div> | ||
| 51 | - </div> | ||
| 52 | - </div> | ||
| 53 | 42 | ||
| 54 | - <!-- Stats Grid --> | 43 | + <!-- 动态标签 --> |
| 55 | - <div class="px-[32rpx] mt-[24rpx]"> | 44 | + <div v-if="productDetail.tags && productDetail.tags.length" class="flex flex-wrap gap-[16rpx]"> |
| 56 | - <div class="grid grid-cols-2 gap-[24rpx]"> | ||
| 57 | <div | 45 | <div |
| 58 | - v-for="(item, index) in stats" | 46 | + v-for="tag in productDetail.tags" |
| 59 | - :key="index" | 47 | + :key="tag.id" |
| 60 | - class="bg-white rounded-[24rpx] p-[32rpx] border border-gray-100" | 48 | + class="rounded-[8rpx] px-[16rpx] py-[6rpx]" |
| 49 | + :style="{ | ||
| 50 | + backgroundColor: tag.bg_color, | ||
| 51 | + color: tag.text_color | ||
| 52 | + }" | ||
| 61 | > | 53 | > |
| 62 | - <div class="text-[#6B7280] text-[24rpx] mb-[12rpx]">{{ item.label }}</div> | 54 | + <span class="text-[24rpx]">{{ tag.name }}</span> |
| 63 | - <div class="text-[#1F2937] text-[30rpx] font-medium">{{ item.value }}</div> | ||
| 64 | </div> | 55 | </div> |
| 65 | </div> | 56 | </div> |
| 66 | </div> | 57 | </div> |
| 67 | 58 | ||
| 68 | - <!-- Product Features --> | 59 | + <!-- Product Description (富文本) --> |
| 69 | - <div class="px-[32rpx] mt-[32rpx]"> | 60 | + <div v-if="productDetail.product_description" class="px-[32rpx] mt-[32rpx]"> |
| 70 | <div class="bg-white rounded-[32rpx] p-[40rpx]"> | 61 | <div class="bg-white rounded-[32rpx] p-[40rpx]"> |
| 71 | - <h2 class="text-[#1F2937] text-[32rpx] font-bold mb-[32rpx]">产品特色</h2> | 62 | + <h2 class="text-[#1F2937] text-[32rpx] font-bold mb-[32rpx]">产品描述</h2> |
| 72 | - <div class="flex flex-col gap-[32rpx]"> | 63 | + <!-- 使用 rich-text 渲染富文本 --> |
| 73 | - <div v-for="(feature, index) in features" :key="index" class="flex items-start"> | 64 | + <rich-text :nodes="productDetail.product_description" class="text-[#4B5563] text-[28rpx] leading-[1.6]"></rich-text> |
| 74 | - <div class="w-[48rpx] h-[48rpx] rounded-full bg-blue-50 flex items-center justify-center mr-[24rpx] flex-shrink-0"> | ||
| 75 | - <IconFont name="Check" size="14" color="#2563EB" /> | ||
| 76 | - </div> | ||
| 77 | - <div class="flex-1"> | ||
| 78 | - <div class="text-[#1F2937] text-[28rpx] font-medium leading-[1.4]">{{ feature.title }}</div> | ||
| 79 | - <div class="text-[#6B7280] text-[24rpx] mt-[8rpx] leading-[1.4]">{{ feature.desc }}</div> | ||
| 80 | - </div> | ||
| 81 | - </div> | ||
| 82 | - </div> | ||
| 83 | </div> | 65 | </div> |
| 84 | </div> | 66 | </div> |
| 85 | 67 | ||
| 86 | <!-- Attachments --> | 68 | <!-- Attachments --> |
| 87 | - <div class="px-[32rpx] mt-[32rpx]"> | 69 | + <div v-if="productDetail.documents && productDetail.documents.length" class="px-[32rpx] mt-[32rpx]"> |
| 88 | <div class="bg-white rounded-[32rpx] p-[40rpx]"> | 70 | <div class="bg-white rounded-[32rpx] p-[40rpx]"> |
| 89 | <h2 class="text-[#1F2937] text-[32rpx] font-bold mb-[32rpx]">相关附件</h2> | 71 | <h2 class="text-[#1F2937] text-[32rpx] font-bold mb-[32rpx]">相关附件</h2> |
| 90 | <div class="flex flex-col gap-[24rpx]"> | 72 | <div class="flex flex-col gap-[24rpx]"> |
| 91 | <div | 73 | <div |
| 92 | - v-for="(file, index) in files" | 74 | + v-for="(doc, index) in productDetail.documents" |
| 93 | :key="index" | 75 | :key="index" |
| 94 | class="flex flex-col p-[24rpx] bg-gray-50 rounded-[16rpx]" | 76 | class="flex flex-col p-[24rpx] bg-gray-50 rounded-[16rpx]" |
| 95 | > | 77 | > |
| 96 | - <div class="flex items-center justify-between mb-[8rpx]"> | 78 | + <div class="flex items-center justify-between"> |
| 97 | <div class="flex items-center flex-1 mr-[24rpx]"> | 79 | <div class="flex items-center flex-1 mr-[24rpx]"> |
| 98 | <image | 80 | <image |
| 99 | - :src="getDocumentIcon(file.fileName)" | 81 | + :src="getDocumentIcon(doc.file_name)" |
| 100 | class="w-[48rpx] h-[48rpx] mr-[24rpx]" | 82 | class="w-[48rpx] h-[48rpx] mr-[24rpx]" |
| 101 | mode="aspectFit" | 83 | mode="aspectFit" |
| 102 | /> | 84 | /> |
| 103 | <div class="flex flex-col"> | 85 | <div class="flex flex-col"> |
| 104 | - <span class="text-[#1F2937] text-[28rpx] font-medium mb-[4rpx] line-clamp-1">{{ file.name }}</span> | 86 | + <span class="text-[#1F2937] text-[28rpx] font-medium mb-[4rpx] line-clamp-1">{{ doc.file_name }}</span> |
| 105 | - <span class="text-[#9CA3AF] text-[24rpx]">{{ file.size }}</span> | 87 | + <span class="text-[#9CA3AF] text-[24rpx]">{{ doc.file_size_formatted }}</span> |
| 106 | </div> | 88 | </div> |
| 107 | </div> | 89 | </div> |
| 108 | - <IconFont name="eye" size="20" color="#2563EB" @tap="viewFile(file)" /> | 90 | + <IconFont name="eye" size="20" color="#2563EB" @tap="viewDocument(doc)" /> |
| 91 | + </div> | ||
| 109 | </div> | 92 | </div> |
| 110 | </div> | 93 | </div> |
| 111 | </div> | 94 | </div> |
| ... | @@ -125,12 +108,75 @@ import IconFont from '@/components/IconFont.vue' | ... | @@ -125,12 +108,75 @@ import IconFont from '@/components/IconFont.vue' |
| 125 | import { useFileOperation } from '@/composables/useFileOperation' | 108 | import { useFileOperation } from '@/composables/useFileOperation' |
| 126 | import Taro, { useLoad } from '@tarojs/taro' | 109 | import Taro, { useLoad } from '@tarojs/taro' |
| 127 | import { getDocumentIcon } from '@/utils/documentIcons' | 110 | import { getDocumentIcon } from '@/utils/documentIcons' |
| 111 | +import { detailAPI } from '@/api/get_product' | ||
| 128 | 112 | ||
| 129 | const { viewFile } = useFileOperation() | 113 | const { viewFile } = useFileOperation() |
| 130 | 114 | ||
| 131 | // 接收页面参数 | 115 | // 接收页面参数 |
| 132 | const productId = ref(null) | 116 | const productId = ref(null) |
| 133 | 117 | ||
| 118 | +// 加载状态 | ||
| 119 | +const loading = ref(true) | ||
| 120 | + | ||
| 121 | +// 产品详情数据 | ||
| 122 | +const productDetail = ref({ | ||
| 123 | + id: null, | ||
| 124 | + product_name: '', | ||
| 125 | + recommend: '', | ||
| 126 | + product_description: '', | ||
| 127 | + cover_image: '', | ||
| 128 | + tags: [], | ||
| 129 | + documents: [] | ||
| 130 | +}) | ||
| 131 | + | ||
| 132 | +/** | ||
| 133 | + * 获取产品详情 | ||
| 134 | + * | ||
| 135 | + * @description 调用 detailAPI 获取产品详情数据 | ||
| 136 | + * @param {string} id - 产品ID | ||
| 137 | + */ | ||
| 138 | +const fetchProductDetail = async (id) => { | ||
| 139 | + try { | ||
| 140 | + loading.value = true | ||
| 141 | + | ||
| 142 | + const res = await detailAPI({ | ||
| 143 | + i: id | ||
| 144 | + }) | ||
| 145 | + | ||
| 146 | + if (res.code === 1 && res.data) { | ||
| 147 | + productDetail.value = res.data | ||
| 148 | + } else { | ||
| 149 | + Taro.showToast({ | ||
| 150 | + title: res.msg || '获取产品详情失败', | ||
| 151 | + icon: 'none', | ||
| 152 | + duration: 2000 | ||
| 153 | + }) | ||
| 154 | + } | ||
| 155 | + } catch (err) { | ||
| 156 | + console.error('获取产品详情失败:', err) | ||
| 157 | + Taro.showToast({ | ||
| 158 | + title: '网络错误,请重试', | ||
| 159 | + icon: 'none', | ||
| 160 | + duration: 2000 | ||
| 161 | + }) | ||
| 162 | + } finally { | ||
| 163 | + loading.value = false | ||
| 164 | + } | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +/** | ||
| 168 | + * 查看文档 | ||
| 169 | + * | ||
| 170 | + * @description 打开文档预览 | ||
| 171 | + * @param {Object} doc - 文档对象 | ||
| 172 | + */ | ||
| 173 | +const viewDocument = (doc) => { | ||
| 174 | + viewFile({ | ||
| 175 | + fileName: doc.file_name, | ||
| 176 | + downloadUrl: doc.file_url | ||
| 177 | + }) | ||
| 178 | +} | ||
| 179 | + | ||
| 134 | useLoad((options) => { | 180 | useLoad((options) => { |
| 135 | console.log('产品详情页参数:', options) | 181 | console.log('产品详情页参数:', options) |
| 136 | 182 | ||
| ... | @@ -138,11 +184,11 @@ useLoad((options) => { | ... | @@ -138,11 +184,11 @@ useLoad((options) => { |
| 138 | productId.value = options.id | 184 | productId.value = options.id |
| 139 | console.log('产品ID:', productId.value) | 185 | console.log('产品ID:', productId.value) |
| 140 | 186 | ||
| 141 | - // TODO: 根据 productId 获取产品详情数据 | 187 | + // 获取产品详情数据 |
| 142 | - // 这里可以调用 API 获取对应产品的数据 | ||
| 143 | fetchProductDetail(options.id) | 188 | fetchProductDetail(options.id) |
| 144 | } else { | 189 | } else { |
| 145 | console.warn('未接收到产品ID') | 190 | console.warn('未接收到产品ID') |
| 191 | + loading.value = false | ||
| 146 | Taro.showToast({ | 192 | Taro.showToast({ |
| 147 | title: '产品ID不存在', | 193 | title: '产品ID不存在', |
| 148 | icon: 'none', | 194 | icon: 'none', |
| ... | @@ -151,107 +197,6 @@ useLoad((options) => { | ... | @@ -151,107 +197,6 @@ useLoad((options) => { |
| 151 | } | 197 | } |
| 152 | }) | 198 | }) |
| 153 | 199 | ||
| 154 | -// 根据 ID 获取产品详情(模拟) | 200 | +// Random banner image (fallback) |
| 155 | -const fetchProductDetail = async (id) => { | ||
| 156 | - console.log('正在获取产品ID', id, '的详情...') | ||
| 157 | - | ||
| 158 | - // TODO: 实际调用 API | ||
| 159 | - // const res = await getProductDetailAPI({ i: id }) | ||
| 160 | - // if (res.code === 1) { | ||
| 161 | - // // 更新产品数据 | ||
| 162 | - // } | ||
| 163 | - | ||
| 164 | - // 模拟根据不同ID显示不同产品 | ||
| 165 | - const productNames = { | ||
| 166 | - '1': '家庭财富传承保障计划(分红)', | ||
| 167 | - '2': '儿童教育金储备方案(分红)' | ||
| 168 | - } | ||
| 169 | - | ||
| 170 | - if (productNames[id]) { | ||
| 171 | - console.log('产品名称:', productNames[id]) | ||
| 172 | - } | ||
| 173 | -} | ||
| 174 | - | ||
| 175 | -// Random banner image | ||
| 176 | const bannerImage = `https://picsum.photos/seed/${Math.floor(Math.random() * 1000)}/750/420` | 201 | const bannerImage = `https://picsum.photos/seed/${Math.floor(Math.random() * 1000)}/750/420` |
| 177 | - | ||
| 178 | -const stats = ref([ | ||
| 179 | - { label: '投保年龄', value: '30天-70周岁' }, | ||
| 180 | - { label: '保障期限', value: '终身' }, | ||
| 181 | - { label: '缴费方式', value: '3/5/10年交' }, | ||
| 182 | - { label: '起投金额', value: '10000元起' } | ||
| 183 | -]) | ||
| 184 | - | ||
| 185 | -const features = ref([ | ||
| 186 | - { title: '身故保险金', desc: '赔付100%基本保额,给家人留爱不留债' }, | ||
| 187 | - { title: '全残保险金', desc: '赔付100%基本保额,生活有保障' }, | ||
| 188 | - { title: '保费豁免', desc: '确诊重疾后免交剩余保费,保障继续有效' }, | ||
| 189 | - { title: '保单贷款', desc: '最高可贷现金价值80%,资金周转灵活' } | ||
| 190 | -]) | ||
| 191 | - | ||
| 192 | -const files = ref([ | ||
| 193 | - { | ||
| 194 | - name: '产品条款.pdf', | ||
| 195 | - size: '2.3MB', | ||
| 196 | - fileName: '产品条款.pdf', | ||
| 197 | - downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/test.pdf', | ||
| 198 | - iconName: 'order', | ||
| 199 | - iconColor: '#EF4444', | ||
| 200 | - fileType: 'pdf', | ||
| 201 | - showTip: false, | ||
| 202 | - tipText: '' | ||
| 203 | - }, | ||
| 204 | - { | ||
| 205 | - name: '投保须知.docx', | ||
| 206 | - size: '1.8MB', | ||
| 207 | - fileName: '投保须知.docx', | ||
| 208 | - downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/%E7%94%A8%E6%88%B7%E5%8D%8F%E8%AE%AE%E6%9C%80%E7%BB%88v3.1.docx', | ||
| 209 | - iconName: 'order', | ||
| 210 | - iconColor: '#2563EB', | ||
| 211 | - fileType: 'docx', | ||
| 212 | - showTip: true, | ||
| 213 | - tipText: 'Word 文档可能无法正常显示,建议打开后点击右上角"..."菜单选择"发送给朋友"保存到电脑查看' | ||
| 214 | - }, | ||
| 215 | - { | ||
| 216 | - name: '健康告知.pptx', | ||
| 217 | - size: '3.2MB', | ||
| 218 | - fileName: '健康告知.pptx', | ||
| 219 | - downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/%E8%82%A1%E5%88%A4%E5%90%88%E5%8F%8B%E7%94%A8%E7%9F%A5%E8%AF%86%E8%AF%B4%E6%98%8E20240112110417414.pptx', | ||
| 220 | - iconName: 'order', | ||
| 221 | - iconColor: '#F59E0B', | ||
| 222 | - fileType: 'pptx', | ||
| 223 | - showTip: true, | ||
| 224 | - tipText: 'PPT 文档可能无法正常显示,建议打开后点击右上角"..."菜单选择"发送给朋友"保存到电脑查看' | ||
| 225 | - }, | ||
| 226 | - { | ||
| 227 | - name: '保险责任说明.xlsx', | ||
| 228 | - size: '1.5MB', | ||
| 229 | - fileName: '保险责任说明.xlsx', | ||
| 230 | - downloadUrl: 'https://cdn.ipadbiz.cn/manulife/document/%E7%94%A8%E6%88%B7%E5%8D%8F%E8%AE%AE%E6%9C%80%E7%BB%88v3.1.docx', | ||
| 231 | - iconName: 'order', | ||
| 232 | - iconColor: '#10B981', | ||
| 233 | - fileType: 'xlsx', | ||
| 234 | - showTip: true, | ||
| 235 | - tipText: 'Excel 文档可能无法正常显示,建议打开后点击右上角"..."菜单选择"发送给朋友"保存到电脑查看' | ||
| 236 | - } | ||
| 237 | -]) | ||
| 238 | - | ||
| 239 | -// 收藏状态 | ||
| 240 | -const isCollected = ref(false) | ||
| 241 | - | ||
| 242 | -// 切换收藏状态 | ||
| 243 | -const toggleCollect = () => { | ||
| 244 | - isCollected.value = !isCollected.value | ||
| 245 | - if (isCollected.value) { | ||
| 246 | - Taro.showToast({ | ||
| 247 | - title: '已收藏', | ||
| 248 | - icon: 'success' | ||
| 249 | - }) | ||
| 250 | - } else { | ||
| 251 | - Taro.showToast({ | ||
| 252 | - title: '已取消收藏', | ||
| 253 | - icon: 'none' | ||
| 254 | - }) | ||
| 255 | - } | ||
| 256 | -} | ||
| 257 | </script> | 202 | </script> | ... | ... |
-
Please register or login to post a comment