hookehuyr

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>
...@@ -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个后端开发中)
......
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 +```
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 +```
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: '臻奇智荟圈',
......
This diff is collapsed. Click to expand it.