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 @@
## 📊 总体进度
- **总接口数**: 27
- **已完成**: 15 (55.6%)
- **总接口数**: 29
- **已完成**: 15 (51.7%)
- **联调中**: 0 (0%)
- **已废弃**: 3 (11.1%)
- **待联调**: 9 (33.3%)
- **已废弃**: 3 (10.3%)
- **待联调**: 9 (31.0%)
- **待后端开发**: 2 (6.9%)
- **有阻塞**: 0
---
**📝 最近更新** (2026-02-09):
- 🆕 **新增计划书模块**
- 接口1: 提交计划书表单(submitPlanAPI)- 待后端开发
- 接口2: 查询计划书状态(getPlanStatusAPI)- 规划中
-**前端表单已完成**
- 修复表单提交时数据为空的问题
- 添加金额字段格式化显示(分 → 元)
- 实现表单验证和数据准备
- ⚠️ **数据单位规范**
- 金额字段单位为"分"(非"元")
- 存储格式:整数(如 10000 表示 100.00 元)
- 显示格式:除以 100 并保留 2 位小数
- 📝 **详细注意事项**[接口联调注意事项.md](../接口联调注意事项.md)
**📝 最近更新** (2026-02-06):
-**搜索模块联调完成**:searchAPI 接口前端已完成集成
- 支持产品和资料的实时搜索
......@@ -1146,6 +1161,121 @@
---
### 计划书模块
#### 接口 1: 提交计划书表单
**接口信息**
- **接口名称**: `submitPlanAPI`(待实现)
- **接口路径**: `/srv/?a=submit_plan`(待确认)
- **请求方法**: POST
- **负责页面**: `src/components/PlanFormContainer.vue`
- **负责人**: 后端团队
**接口文档更新记录**
| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 |
|------|------|---------|---------|---------|
| 2026-02-09 | v1.0 | 初始版本 | 前端表单已完成,待后端接口开发 | [查看](#) |
**页面调试情况**
| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 |
|------|---------|---------|---------|------|
| 2026-02-09 | `src/components/PlanFormContainer.vue` | 表单提交时数据为空 | 修复 submit() 时序问题,移除立即重置 | ✅ 已解决 |
| 2026-02-09 | `src/components/PlanFormContainer.vue` | 金额显示为 10000 而非 100.00 | 添加 formatAmounts() 格式化显示(分 → 元) | ✅ 已解决 |
**接口状态**: ⏳ 待后端接口开发
**数据单位规范**(重要):
- **金额字段单位**: 分(非元)
- 金额字段列表: `coverage`, `premium`, `amount`, `total_amount`
- 存储格式: 整数(如 `10000` 表示 100.00 元)
- 显示格式: 除以 100 并保留 2 位小数
**转换公式**:
```javascript
// 元 → 分(提交给后端)
const cents = Math.round(yuan * 100)
// 分 → 元(前端显示)
const yuan = (cents / 100).toFixed(2)
```
**请求参数格式**(待确认):
```javascript
{
product_id: 1, // 产品ID
form_sn: 'life-insurance-wiop3e', // 表单模版标识
form_data: { // 表单数据
coverage: 10000, // 保额(分)← 注意单位
gender: 'male',
age: 30,
birthday: '1994-01-01',
smoker: false,
payment_period: 20
}
}
```
**响应格式**(待确认):
```javascript
{
code: 1, // 1 表示成功
data: {
plan_id: 123, // 计划书ID
status: 'processing', // 状态:processing(生成中) | generated(已完成)
download_url: '' // 下载链接(生成完成后才有)
},
msg: '提交成功'
}
```
**备注**:
- ⚠️ **重要**: 所有金额字段内部存储单位都是"分",不是"元"
- ✅ 前端已实现表单验证和数据格式化
- ✅ 日志输出同时显示格式化数据(元)和原始数据(分),便于调试
- ⏳ 后端接口待开发,当前仅为前端测试
- 📝 详细注意事项:[接口联调注意事项](../接口联调注意事项.md)
**实现位置**
- `src/components/PlanFormContainer.vue:250-285` - submit() 函数
- `src/components/PlanFormContainer.vue:220-241` - formatAmounts() 函数
- `src/components/PlanFields/AmountKeyboard.vue` - 金额输入组件
---
#### 接口 2: 查询计划书状态(待实现)
**接口信息**
- **接口名称**: `getPlanStatusAPI`(待实现)
- **接口路径**: `/srv/?a=get_plan_status`(待确认)
- **请求方法**: GET
- **负责页面**: 待确认(计划书结果页?)
- **负责人**: 后端团队
**接口文档更新记录**
| 日期 | 版本 | 变更内容 | 变更原因 | 文档链接 |
|------|------|---------|---------|---------|
| 2026-02-09 | v1.0 | 初始版本 | 接口规划 | [查看](#) |
**页面调试情况**
| 日期 | 调试页面 | 问题记录 | 解决方案 | 状态 |
|------|---------|---------|---------|------|
| - | - | - | - | ⏳ 未开始 |
**接口状态**: ⏳ 未开始
**备注**:
- 用于轮询查询计划书生成状态
- 参数:`plan_id`(计划书ID)
- 返回生成状态和下载链接
- 如需轮询功能,建议使用 `setInterval` 每 2-3 秒查询一次
---
## 📌 快速索引
### 按状态查看
......@@ -1203,13 +1333,13 @@
---
**最后更新时间**: 2026-02-06 17:20
**文档版本**: v2.5
**最后更新时间**: 2026-02-09 00:40
**文档版本**: v2.6
**更新内容**:
- **搜索模块联调完成**:新增 searchAPI 接口,前端已完成集成
- 🆕 **新增可复用卡片组件**:MaterialCard、ProductCard
- 🔄 **页面重构**:搜索页、首页、周热门资料页使用新组件重构,减少代码重复
- 更新总体进度:27个接口(15个已完成,9个待联调,3个已废弃)
- 🆕 **新增计划书模块**:计划书表单提交和状态查询接口
- **前端表单完成**:修复数据为空问题,添加金额格式化
- ⚠️ **数据单位规范**:明确金额字段单位为"分"
- 更新总体进度:29个接口(15个已完成,9个待联调,2个待后端开发,3个已废弃)
**历史版本**:
- v2.1 (2026-02-03 21:00): 产品模块联调完成
......
# 接口联调注意事项
> **文档用途**:记录计划书表单接口联调的关键注意事项和规范
>
> **最后更新**:2026-02-09
> **维护者**:Claude Code
## 📋 目录
- [数据单位规范](#数据单位规范)
- [接口联调流程](#接口联调流程)
- [关键注意事项](#关键注意事项)
- [调试技巧](#调试技巧)
- [常见问题](#常见问题)
---
## 数据单位规范
### ⚠️ 金额字段单位:分(非元)
**重要**:所有金额字段内部存储单位都是 **分**,不是元!
| 字段名 | 类型 | 单位 | 示例 | 显示 |
|--------|------|------|------|------|
| `coverage` | Number | 分 | `10000` | `100.00` 元 |
| `premium` | Number | 分 | `5000` | `50.00` 元 |
| `amount` | Number | 分 | `1000` | `10.00` 元 |
| `total_amount` | Number | 分 | `15000` | `150.00` 元 |
**转换公式**
```javascript
// 元 → 分(提交给后端)
const cents = Math.round(yuan * 100)
// 分 → 元(前端显示)
const yuan = (cents / 100).toFixed(2)
```
**为什么使用"分"?**
- ✅ 避免浮点数精度问题(`0.1 + 0.2 !== 0.3`
- ✅ 整数运算精确可靠
- ✅ 金融行业标准做法
---
## 接口联调流程
### 1. 提交计划书表单
**接口路径**`/srv/?a=submit_plan`(待确认)
**请求参数**
```javascript
{
product_id: 1, // 产品ID
form_sn: 'life-insurance-wiop3e', // 表单模版标识
form_data: { // 表单数据
coverage: 10000, // 保额(分)← 注意单位
gender: 'male',
age: 30,
birthday: '1994-01-01',
smoker: false,
payment_period: 20,
// ... 其他字段
}
}
```
**响应格式**
```javascript
{
code: 1, // 1 表示成功
data: {
plan_id: 123, // 计划书ID
status: 'processing', // 状态:processing(生成中) | generated(已完成)
download_url: '' // 下载链接(生成完成后才有)
},
msg: '提交成功'
}
```
### 2. 查询计划书状态
**接口路径**`/srv/?a=get_plan_status`
**请求参数**
```javascript
{
plan_id: 123 // 计划书ID
}
```
**响应格式**
```javascript
{
code: 1,
data: {
plan_id: 123,
status: 'generated', // processing | generated
download_url: 'https://...' // PDF 下载链接
},
msg: ''
}
```
---
## 关键注意事项
### ⚠️ 1. 金额字段单位必须是"分"
**错误示例**
```javascript
// ❌ 错误:直接发送"元"
{
coverage: 100.00 // 后端会解析错误或精度丢失
}
```
**正确示例**
```javascript
// ✅ 正确:发送"分"
{
coverage: 10000 // 后端接收后再除以100
}
```
### ⚠️ 2. 检查响应码
**必须检查 `res.code === 1`**
```javascript
const res = await submitPlanAPI(params)
if (res.code === 1) {
// 成功
console.log('提交成功:', res.data)
} else {
// 失败
Taro.showToast({
title: res.msg || '提交失败',
icon: 'none'
})
}
```
### ⚠️ 3. 错误处理
**所有 API 调用必须有 `try-catch`**
```javascript
try {
const res = await submitPlanAPI(params)
if (res.code === 1) {
Taro.showToast({ title: '提交成功', icon: 'success' })
} else {
Taro.showToast({ title: res.msg || '提交失败', icon: 'none' })
}
} catch (err) {
console.error('[SubmitPlan] 提交失败:', err)
Taro.showToast({
title: '网络异常,请重试',
icon: 'none'
})
}
```
### ⚠️ 4. 加载状态
**提交时显示 loading**
```javascript
const loading = ref(false)
const submit = async () => {
loading.value = true
try {
await submitPlanAPI(params)
} finally {
loading.value = false
}
}
```
---
## 调试技巧
### 1. 打印请求数据
**提交前打印完整数据**(已实现):
```javascript
console.log('[PlanFormContainer] 提交计划书:', {
product_id: props.product.id,
product_name: props.product.product_name,
form_sn: props.product.form_sn,
form_data: formattedData // ← 格式化后的数据(元)
})
console.log('[PlanFormContainer] 原始数据(分):', formData.value)
```
**打印效果**
```javascript
// 格式化后(便于查看)
form_data: {
coverage: '100.00',
gender: 'male',
age: 30
}
// 原始数据(实际发送)
form_data: {
coverage: 10000,
gender: 'male',
age: 30
}
```
### 2. 网络请求拦截器
**检查 `src/utils/request.js` 中的拦截器配置**
- ✅ 请求拦截器已自动注入 sessionid
- ✅ 响应拦截器已处理 401 自动刷新
- ✅ 超时配置:5 秒
**查看请求日志**
```javascript
// request.js 中的日志
console.log('[Request] URL:', url)
console.log('[Request] Data:', params)
console.log('[Response] Data:', res)
```
### 3. 开发者工具
**微信开发者工具**
1. 点击"调试器" → "Network"
2. 找到对应的请求(`submit_plan`
3. 查看"Headers"和"Payload"
4. 确认金额字段是整数(分)
---
## 常见问题
### Q1: 后端接收到的金额是 `0.00`?
**原因**:前端发送的值是 `100.00`(浮点数),但后端期望的是整数(分)。
**解决方案**:确保发送的是整数(分):
```javascript
// ❌ 错误
form_data: {
coverage: 100.00 // 浮点数
}
// ✅ 正确
form_data: {
coverage: 10000 // 整数
}
```
### Q2: 后端返回的金额如何显示?
**后端返回的金额单位应该是"分"**
```javascript
// 后端返回
{
code: 1,
data: {
coverage: 10000 // 分
}
}
// 前端显示
const displayYuan = (res.data.coverage / 100).toFixed(2)
// displayYuan = '100.00'
```
### Q3: 如何验证金额是否正确?
**验证方法**
```javascript
// 输入 100.00 元
console.log('输入值:', '100.00')
// 存储的值(分)
console.log('存储值:', 10000)
// 显示的值(元)
console.log('显示值:', (10000 / 100).toFixed(2)) // '100.00'
```
---
## 接口联调清单
### 提交前检查
- [ ] 后端接口地址已配置(`src/utils/config.js`
- [ ] 请求路径正确(`/srv/?a=xxx`
- [ ] 请求参数格式已确认
- [ ] 响应格式已确认(`{ code, data, msg }`
- [ ] 金额字段单位已确认(分)
### 提交时验证
- [ ] 金额字段是整数(分)
- [ ] 检查 `res.code === 1`
- [ ] 错误提示用户友好
- [ ] Loading 状态正确显示
### 提交后处理
- [ ] 成功后跳转到计划书列表页
- [ ] 失败后停留在表单页
- [ ] 网络异常有重试机制
- [ ] 轮询状态(如果是生成中的计划书)
---
## 接口定义示例
### 1. 提交计划书
**定义位置**`src/api/index.js`
```javascript
/**
* 提交计划书表单
*
* @param {Object} params - 请求参数
* @param {number} params.product_id - 产品ID
* @param {string} params.form_sn - 表单模版标识
* @param {Object} params.form_data - 表单数据
* @returns {Promise<{code: number, data: Object, msg: string}>}
*
* @example
* const res = await submitPlanAPI({
* product_id: 1,
* form_sn: 'life-insurance-wiop3e',
* form_data: {
* coverage: 10000, // 保额(分)
* gender: 'male',
* age: 30
* }
* })
*/
export const submitPlanAPI = (params) => {
return buildApiUrl('submit_plan', params)
}
```
### 2. 查询计划书状态
```javascript
/**
* 查询计划书生成状态
*
* @param {Object} params - 请求参数
* @param {number} params.plan_id - 计划书ID
* @returns {Promise<{code: number, data: Object, msg: string}>}
*/
export const getPlanStatusAPI = (params) => {
return buildApiUrl('get_plan_status', params)
}
```
---
## 快速参考
### 金额转换工具函数
**位置**`src/utils/amount.js`(建议创建)
```javascript
/**
* 元转分
* @param {number|string} yuan - 元
* @returns {number} 分
*/
export const yuanToCents = (yuan) => {
return Math.round(Number(yuan) * 100)
}
/**
* 分转元
* @param {number} cents - 分
* @returns {string} 元(带2位小数)
*/
export const centsToYuan = (cents) => {
return (cents / 100).toFixed(2)
}
/**
* 格式化金额显示
* @param {number} cents - 分
* @returns {string} 格式化后的金额(如:"10,000.00")
*/
export const formatAmount = (cents) => {
const yuan = (cents / 100).toFixed(2)
const parts = yuan.split('.')
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
return parts.join('.')
}
```
### 使用示例
```javascript
import { yuanToCents, centsToYuan, formatAmount } from '@/utils/amount'
// 用户输入
const input = '100.00'
const cents = yuanToCents(input) // 10000
// 存储
formData.value.coverage = cents
// 显示
const display = formatAmount(cents) // '10,000.00' 或 '100.00'
```
---
## 维护日志
- **2026-02-09**:创建文档,记录金额字段单位规范和联调注意事项
---
## 相关文档
- [项目 CLAUDE.md](../CLAUDE.md) - 项目开发规范
- [API 集成日志](../api-integration-log.md) - API 联调记录
- [变更日志](../CHANGELOG.md) - 版本更新历史