hookehuyr

docs(api): 重组接口文档结构

将独立的接口联调文档合并到统一的 API 集成日志中

变更内容:
- 将计划书模块接口文档合并到 docs/api-docs/API 集成日志.md
- 新增计划书模块(2个接口)
  • 接口1: 提交计划书表单(待后端开发)
  • 接口2: 查询计划书状态(待后端开发)
- 更新总体进度:27 → 29 个接口
- 更新版本号:v2.5 → v2.6
- 删除独立的 docs/接口联调注意事项.md

文档规范:
- 遵循项目统一的接口文档结构
- 所有接口集成记录集中在 API 集成日志中维护

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
...@@ -4,15 +4,30 @@ ...@@ -4,15 +4,30 @@
4 4
5 ## 📊 总体进度 5 ## 📊 总体进度
6 6
7 -- **总接口数**: 27 7 +- **总接口数**: 29
8 -- **已完成**: 15 (55.6%) 8 +- **已完成**: 15 (51.7%)
9 - **联调中**: 0 (0%) 9 - **联调中**: 0 (0%)
10 -- **已废弃**: 3 (11.1%) 10 +- **已废弃**: 3 (10.3%)
11 -- **待联调**: 9 (33.3%) 11 +- **待联调**: 9 (31.0%)
12 +- **待后端开发**: 2 (6.9%)
12 - **有阻塞**: 0 13 - **有阻塞**: 0
13 14
14 --- 15 ---
15 16
17 +**📝 最近更新** (2026-02-09):
18 +- 🆕 **新增计划书模块**
19 + - 接口1: 提交计划书表单(submitPlanAPI)- 待后端开发
20 + - 接口2: 查询计划书状态(getPlanStatusAPI)- 规划中
21 +-**前端表单已完成**
22 + - 修复表单提交时数据为空的问题
23 + - 添加金额字段格式化显示(分 → 元)
24 + - 实现表单验证和数据准备
25 +- ⚠️ **数据单位规范**
26 + - 金额字段单位为"分"(非"元")
27 + - 存储格式:整数(如 10000 表示 100.00 元)
28 + - 显示格式:除以 100 并保留 2 位小数
29 +- 📝 **详细注意事项**[接口联调注意事项.md](../接口联调注意事项.md)
30 +
16 **📝 最近更新** (2026-02-06): 31 **📝 最近更新** (2026-02-06):
17 -**搜索模块联调完成**:searchAPI 接口前端已完成集成 32 -**搜索模块联调完成**:searchAPI 接口前端已完成集成
18 - 支持产品和资料的实时搜索 33 - 支持产品和资料的实时搜索
...@@ -1146,6 +1161,121 @@ ...@@ -1146,6 +1161,121 @@
1146 1161
1147 --- 1162 ---
1148 1163
1164 +### 计划书模块
1165 +
1166 +#### 接口 1: 提交计划书表单
1167 +
1168 +**接口信息**
1169 +- **接口名称**: `submitPlanAPI`(待实现)
1170 +- **接口路径**: `/srv/?a=submit_plan`(待确认)
1171 +- **请求方法**: POST
1172 +- **负责页面**: `src/components/PlanFormContainer.vue`
1173 +- **负责人**: 后端团队
1174 +
1175 +**接口文档更新记录**
1176 +
1177 +| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 |
1178 +|------|------|---------|---------|---------|
1179 +| 2026-02-09 | v1.0 | 初始版本 | 前端表单已完成,待后端接口开发 | [查看](#) |
1180 +
1181 +**页面调试情况**
1182 +
1183 +| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 |
1184 +|------|---------|---------|---------|------|
1185 +| 2026-02-09 | `src/components/PlanFormContainer.vue` | 表单提交时数据为空 | 修复 submit() 时序问题,移除立即重置 | ✅ 已解决 |
1186 +| 2026-02-09 | `src/components/PlanFormContainer.vue` | 金额显示为 10000 而非 100.00 | 添加 formatAmounts() 格式化显示(分 → 元) | ✅ 已解决 |
1187 +
1188 +**接口状态**: ⏳ 待后端接口开发
1189 +
1190 +**数据单位规范**(重要):
1191 +- **金额字段单位**: 分(非元)
1192 +- 金额字段列表: `coverage`, `premium`, `amount`, `total_amount`
1193 +- 存储格式: 整数(如 `10000` 表示 100.00 元)
1194 +- 显示格式: 除以 100 并保留 2 位小数
1195 +
1196 +**转换公式**:
1197 +```javascript
1198 +// 元 → 分(提交给后端)
1199 +const cents = Math.round(yuan * 100)
1200 +
1201 +// 分 → 元(前端显示)
1202 +const yuan = (cents / 100).toFixed(2)
1203 +```
1204 +
1205 +**请求参数格式**(待确认):
1206 +```javascript
1207 +{
1208 + product_id: 1, // 产品ID
1209 + form_sn: 'life-insurance-wiop3e', // 表单模版标识
1210 + form_data: { // 表单数据
1211 + coverage: 10000, // 保额(分)← 注意单位
1212 + gender: 'male',
1213 + age: 30,
1214 + birthday: '1994-01-01',
1215 + smoker: false,
1216 + payment_period: 20
1217 + }
1218 +}
1219 +```
1220 +
1221 +**响应格式**(待确认):
1222 +```javascript
1223 +{
1224 + code: 1, // 1 表示成功
1225 + data: {
1226 + plan_id: 123, // 计划书ID
1227 + status: 'processing', // 状态:processing(生成中) | generated(已完成)
1228 + download_url: '' // 下载链接(生成完成后才有)
1229 + },
1230 + msg: '提交成功'
1231 +}
1232 +```
1233 +
1234 +**备注**:
1235 +- ⚠️ **重要**: 所有金额字段内部存储单位都是"分",不是"元"
1236 +- ✅ 前端已实现表单验证和数据格式化
1237 +- ✅ 日志输出同时显示格式化数据(元)和原始数据(分),便于调试
1238 +- ⏳ 后端接口待开发,当前仅为前端测试
1239 +- 📝 详细注意事项:[接口联调注意事项](../接口联调注意事项.md)
1240 +
1241 +**实现位置**
1242 +- `src/components/PlanFormContainer.vue:250-285` - submit() 函数
1243 +- `src/components/PlanFormContainer.vue:220-241` - formatAmounts() 函数
1244 +- `src/components/PlanFields/AmountKeyboard.vue` - 金额输入组件
1245 +
1246 +---
1247 +
1248 +#### 接口 2: 查询计划书状态(待实现)
1249 +
1250 +**接口信息**
1251 +- **接口名称**: `getPlanStatusAPI`(待实现)
1252 +- **接口路径**: `/srv/?a=get_plan_status`(待确认)
1253 +- **请求方法**: GET
1254 +- **负责页面**: 待确认(计划书结果页?)
1255 +- **负责人**: 后端团队
1256 +
1257 +**接口文档更新记录**
1258 +
1259 +| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 |
1260 +|------|------|---------|---------|---------|
1261 +| 2026-02-09 | v1.0 | 初始版本 | 接口规划 | [查看](#) |
1262 +
1263 +**页面调试情况**
1264 +
1265 +| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 |
1266 +|------|---------|---------|---------|------|
1267 +| - | - | - | - | ⏳ 未开始 |
1268 +
1269 +**接口状态**: ⏳ 未开始
1270 +
1271 +**备注**:
1272 +- 用于轮询查询计划书生成状态
1273 +- 参数:`plan_id`(计划书ID)
1274 +- 返回生成状态和下载链接
1275 +- 如需轮询功能,建议使用 `setInterval` 每 2-3 秒查询一次
1276 +
1277 +---
1278 +
1149 ## 📌 快速索引 1279 ## 📌 快速索引
1150 1280
1151 ### 按状态查看 1281 ### 按状态查看
...@@ -1203,13 +1333,13 @@ ...@@ -1203,13 +1333,13 @@
1203 1333
1204 --- 1334 ---
1205 1335
1206 -**最后更新时间**: 2026-02-06 17:20 1336 +**最后更新时间**: 2026-02-09 00:40
1207 -**文档版本**: v2.5 1337 +**文档版本**: v2.6
1208 **更新内容**: 1338 **更新内容**:
1209 -- **搜索模块联调完成**:新增 searchAPI 接口,前端已完成集成 1339 +- 🆕 **新增计划书模块**:计划书表单提交和状态查询接口
1210 -- 🆕 **新增可复用卡片组件**:MaterialCard、ProductCard 1340 +- **前端表单完成**:修复数据为空问题,添加金额格式化
1211 -- 🔄 **页面重构**:搜索页、首页、周热门资料页使用新组件重构,减少代码重复 1341 +- ⚠️ **数据单位规范**:明确金额字段单位为"分"
1212 -- 更新总体进度:27个接口(15个已完成,9个待联调,3个已废弃) 1342 +- 更新总体进度:29个接口(15个已完成,9个待联调,2个待后端开发,3个已废弃)
1213 1343
1214 **历史版本**: 1344 **历史版本**:
1215 - v2.1 (2026-02-03 21:00): 产品模块联调完成 1345 - v2.1 (2026-02-03 21:00): 产品模块联调完成
......
1 -# 接口联调注意事项
2 -
3 -> **文档用途**:记录计划书表单接口联调的关键注意事项和规范
4 ->
5 -> **最后更新**:2026-02-09
6 -> **维护者**:Claude Code
7 -
8 -## 📋 目录
9 -
10 -- [数据单位规范](#数据单位规范)
11 -- [接口联调流程](#接口联调流程)
12 -- [关键注意事项](#关键注意事项)
13 -- [调试技巧](#调试技巧)
14 -- [常见问题](#常见问题)
15 -
16 ----
17 -
18 -## 数据单位规范
19 -
20 -### ⚠️ 金额字段单位:分(非元)
21 -
22 -**重要**:所有金额字段内部存储单位都是 **分**,不是元!
23 -
24 -| 字段名 | 类型 | 单位 | 示例 | 显示 |
25 -|--------|------|------|------|------|
26 -| `coverage` | Number | 分 | `10000` | `100.00` 元 |
27 -| `premium` | Number | 分 | `5000` | `50.00` 元 |
28 -| `amount` | Number | 分 | `1000` | `10.00` 元 |
29 -| `total_amount` | Number | 分 | `15000` | `150.00` 元 |
30 -
31 -**转换公式**
32 -```javascript
33 -// 元 → 分(提交给后端)
34 -const cents = Math.round(yuan * 100)
35 -
36 -// 分 → 元(前端显示)
37 -const yuan = (cents / 100).toFixed(2)
38 -```
39 -
40 -**为什么使用"分"?**
41 -- ✅ 避免浮点数精度问题(`0.1 + 0.2 !== 0.3`
42 -- ✅ 整数运算精确可靠
43 -- ✅ 金融行业标准做法
44 -
45 ----
46 -
47 -## 接口联调流程
48 -
49 -### 1. 提交计划书表单
50 -
51 -**接口路径**`/srv/?a=submit_plan`(待确认)
52 -
53 -**请求参数**
54 -```javascript
55 -{
56 - product_id: 1, // 产品ID
57 - form_sn: 'life-insurance-wiop3e', // 表单模版标识
58 - form_data: { // 表单数据
59 - coverage: 10000, // 保额(分)← 注意单位
60 - gender: 'male',
61 - age: 30,
62 - birthday: '1994-01-01',
63 - smoker: false,
64 - payment_period: 20,
65 - // ... 其他字段
66 - }
67 -}
68 -```
69 -
70 -**响应格式**
71 -```javascript
72 -{
73 - code: 1, // 1 表示成功
74 - data: {
75 - plan_id: 123, // 计划书ID
76 - status: 'processing', // 状态:processing(生成中) | generated(已完成)
77 - download_url: '' // 下载链接(生成完成后才有)
78 - },
79 - msg: '提交成功'
80 -}
81 -```
82 -
83 -### 2. 查询计划书状态
84 -
85 -**接口路径**`/srv/?a=get_plan_status`
86 -
87 -**请求参数**
88 -```javascript
89 -{
90 - plan_id: 123 // 计划书ID
91 -}
92 -```
93 -
94 -**响应格式**
95 -```javascript
96 -{
97 - code: 1,
98 - data: {
99 - plan_id: 123,
100 - status: 'generated', // processing | generated
101 - download_url: 'https://...' // PDF 下载链接
102 - },
103 - msg: ''
104 -}
105 -```
106 -
107 ----
108 -
109 -## 关键注意事项
110 -
111 -### ⚠️ 1. 金额字段单位必须是"分"
112 -
113 -**错误示例**
114 -```javascript
115 -// ❌ 错误:直接发送"元"
116 -{
117 - coverage: 100.00 // 后端会解析错误或精度丢失
118 -}
119 -```
120 -
121 -**正确示例**
122 -```javascript
123 -// ✅ 正确:发送"分"
124 -{
125 - coverage: 10000 // 后端接收后再除以100
126 -}
127 -```
128 -
129 -### ⚠️ 2. 检查响应码
130 -
131 -**必须检查 `res.code === 1`**
132 -```javascript
133 -const res = await submitPlanAPI(params)
134 -
135 -if (res.code === 1) {
136 - // 成功
137 - console.log('提交成功:', res.data)
138 -} else {
139 - // 失败
140 - Taro.showToast({
141 - title: res.msg || '提交失败',
142 - icon: 'none'
143 - })
144 -}
145 -```
146 -
147 -### ⚠️ 3. 错误处理
148 -
149 -**所有 API 调用必须有 `try-catch`**
150 -```javascript
151 -try {
152 - const res = await submitPlanAPI(params)
153 -
154 - if (res.code === 1) {
155 - Taro.showToast({ title: '提交成功', icon: 'success' })
156 - } else {
157 - Taro.showToast({ title: res.msg || '提交失败', icon: 'none' })
158 - }
159 -} catch (err) {
160 - console.error('[SubmitPlan] 提交失败:', err)
161 - Taro.showToast({
162 - title: '网络异常,请重试',
163 - icon: 'none'
164 - })
165 -}
166 -```
167 -
168 -### ⚠️ 4. 加载状态
169 -
170 -**提交时显示 loading**
171 -```javascript
172 -const loading = ref(false)
173 -
174 -const submit = async () => {
175 - loading.value = true
176 -
177 - try {
178 - await submitPlanAPI(params)
179 - } finally {
180 - loading.value = false
181 - }
182 -}
183 -```
184 -
185 ----
186 -
187 -## 调试技巧
188 -
189 -### 1. 打印请求数据
190 -
191 -**提交前打印完整数据**(已实现):
192 -```javascript
193 -console.log('[PlanFormContainer] 提交计划书:', {
194 - product_id: props.product.id,
195 - product_name: props.product.product_name,
196 - form_sn: props.product.form_sn,
197 - form_data: formattedData // ← 格式化后的数据(元)
198 -})
199 -
200 -console.log('[PlanFormContainer] 原始数据(分):', formData.value)
201 -```
202 -
203 -**打印效果**
204 -```javascript
205 -// 格式化后(便于查看)
206 -form_data: {
207 - coverage: '100.00',
208 - gender: 'male',
209 - age: 30
210 -}
211 -
212 -// 原始数据(实际发送)
213 -form_data: {
214 - coverage: 10000,
215 - gender: 'male',
216 - age: 30
217 -}
218 -```
219 -
220 -### 2. 网络请求拦截器
221 -
222 -**检查 `src/utils/request.js` 中的拦截器配置**
223 -- ✅ 请求拦截器已自动注入 sessionid
224 -- ✅ 响应拦截器已处理 401 自动刷新
225 -- ✅ 超时配置:5 秒
226 -
227 -**查看请求日志**
228 -```javascript
229 -// request.js 中的日志
230 -console.log('[Request] URL:', url)
231 -console.log('[Request] Data:', params)
232 -console.log('[Response] Data:', res)
233 -```
234 -
235 -### 3. 开发者工具
236 -
237 -**微信开发者工具**
238 -1. 点击"调试器" → "Network"
239 -2. 找到对应的请求(`submit_plan`
240 -3. 查看"Headers"和"Payload"
241 -4. 确认金额字段是整数(分)
242 -
243 ----
244 -
245 -## 常见问题
246 -
247 -### Q1: 后端接收到的金额是 `0.00`?
248 -
249 -**原因**:前端发送的值是 `100.00`(浮点数),但后端期望的是整数(分)。
250 -
251 -**解决方案**:确保发送的是整数(分):
252 -```javascript
253 -// ❌ 错误
254 -form_data: {
255 - coverage: 100.00 // 浮点数
256 -}
257 -
258 -// ✅ 正确
259 -form_data: {
260 - coverage: 10000 // 整数
261 -}
262 -```
263 -
264 -### Q2: 后端返回的金额如何显示?
265 -
266 -**后端返回的金额单位应该是"分"**
267 -```javascript
268 -// 后端返回
269 -{
270 - code: 1,
271 - data: {
272 - coverage: 10000 // 分
273 - }
274 -}
275 -
276 -// 前端显示
277 -const displayYuan = (res.data.coverage / 100).toFixed(2)
278 -// displayYuan = '100.00'
279 -```
280 -
281 -### Q3: 如何验证金额是否正确?
282 -
283 -**验证方法**
284 -```javascript
285 -// 输入 100.00 元
286 -console.log('输入值:', '100.00')
287 -
288 -// 存储的值(分)
289 -console.log('存储值:', 10000)
290 -
291 -// 显示的值(元)
292 -console.log('显示值:', (10000 / 100).toFixed(2)) // '100.00'
293 -```
294 -
295 ----
296 -
297 -## 接口联调清单
298 -
299 -### 提交前检查
300 -
301 -- [ ] 后端接口地址已配置(`src/utils/config.js`
302 -- [ ] 请求路径正确(`/srv/?a=xxx`
303 -- [ ] 请求参数格式已确认
304 -- [ ] 响应格式已确认(`{ code, data, msg }`
305 -- [ ] 金额字段单位已确认(分)
306 -
307 -### 提交时验证
308 -
309 -- [ ] 金额字段是整数(分)
310 -- [ ] 检查 `res.code === 1`
311 -- [ ] 错误提示用户友好
312 -- [ ] Loading 状态正确显示
313 -
314 -### 提交后处理
315 -
316 -- [ ] 成功后跳转到计划书列表页
317 -- [ ] 失败后停留在表单页
318 -- [ ] 网络异常有重试机制
319 -- [ ] 轮询状态(如果是生成中的计划书)
320 -
321 ----
322 -
323 -## 接口定义示例
324 -
325 -### 1. 提交计划书
326 -
327 -**定义位置**`src/api/index.js`
328 -
329 -```javascript
330 -/**
331 - * 提交计划书表单
332 - *
333 - * @param {Object} params - 请求参数
334 - * @param {number} params.product_id - 产品ID
335 - * @param {string} params.form_sn - 表单模版标识
336 - * @param {Object} params.form_data - 表单数据
337 - * @returns {Promise<{code: number, data: Object, msg: string}>}
338 - *
339 - * @example
340 - * const res = await submitPlanAPI({
341 - * product_id: 1,
342 - * form_sn: 'life-insurance-wiop3e',
343 - * form_data: {
344 - * coverage: 10000, // 保额(分)
345 - * gender: 'male',
346 - * age: 30
347 - * }
348 - * })
349 - */
350 -export const submitPlanAPI = (params) => {
351 - return buildApiUrl('submit_plan', params)
352 -}
353 -```
354 -
355 -### 2. 查询计划书状态
356 -
357 -```javascript
358 -/**
359 - * 查询计划书生成状态
360 - *
361 - * @param {Object} params - 请求参数
362 - * @param {number} params.plan_id - 计划书ID
363 - * @returns {Promise<{code: number, data: Object, msg: string}>}
364 - */
365 -export const getPlanStatusAPI = (params) => {
366 - return buildApiUrl('get_plan_status', params)
367 -}
368 -```
369 -
370 ----
371 -
372 -## 快速参考
373 -
374 -### 金额转换工具函数
375 -
376 -**位置**`src/utils/amount.js`(建议创建)
377 -
378 -```javascript
379 -/**
380 - * 元转分
381 - * @param {number|string} yuan - 元
382 - * @returns {number} 分
383 - */
384 -export const yuanToCents = (yuan) => {
385 - return Math.round(Number(yuan) * 100)
386 -}
387 -
388 -/**
389 - * 分转元
390 - * @param {number} cents - 分
391 - * @returns {string} 元(带2位小数)
392 - */
393 -export const centsToYuan = (cents) => {
394 - return (cents / 100).toFixed(2)
395 -}
396 -
397 -/**
398 - * 格式化金额显示
399 - * @param {number} cents - 分
400 - * @returns {string} 格式化后的金额(如:"10,000.00")
401 - */
402 -export const formatAmount = (cents) => {
403 - const yuan = (cents / 100).toFixed(2)
404 - const parts = yuan.split('.')
405 - parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
406 - return parts.join('.')
407 -}
408 -```
409 -
410 -### 使用示例
411 -
412 -```javascript
413 -import { yuanToCents, centsToYuan, formatAmount } from '@/utils/amount'
414 -
415 -// 用户输入
416 -const input = '100.00'
417 -const cents = yuanToCents(input) // 10000
418 -
419 -// 存储
420 -formData.value.coverage = cents
421 -
422 -// 显示
423 -const display = formatAmount(cents) // '10,000.00' 或 '100.00'
424 -```
425 -
426 ----
427 -
428 -## 维护日志
429 -
430 -- **2026-02-09**:创建文档,记录金额字段单位规范和联调注意事项
431 -
432 ----
433 -
434 -## 相关文档
435 -
436 -- [项目 CLAUDE.md](../CLAUDE.md) - 项目开发规范
437 -- [API 集成日志](../api-integration-log.md) - API 联调记录
438 -- [变更日志](../CHANGELOG.md) - 版本更新历史