接口联调注意事项.md 8.88 KB

接口联调注意事项

文档用途:记录计划书表单接口联调的关键注意事项和规范

最后更新: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

转换公式

// 元 → 分(提交给后端)
const cents = Math.round(yuan * 100)

// 分 → 元(前端显示)
const yuan = (cents / 100).toFixed(2)

为什么使用"分"?

  • ✅ 避免浮点数精度问题(0.1 + 0.2 !== 0.3
  • ✅ 整数运算精确可靠
  • ✅ 金融行业标准做法

接口联调流程

1. 提交计划书表单

接口路径/srv/?a=submit_plan(待确认)

请求参数

{
  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,
    // ... 其他字段
  }
}

响应格式

{
  code: 1,                        // 1 表示成功
  data: {
    plan_id: 123,                // 计划书ID
    status: 'processing',         // 状态:processing(生成中) | generated(已完成)
    download_url: ''              // 下载链接(生成完成后才有)
  },
  msg: '提交成功'
}

2. 查询计划书状态

接口路径/srv/?a=get_plan_status

请求参数

{
  plan_id: 123                    // 计划书ID
}

响应格式

{
  code: 1,
  data: {
    plan_id: 123,
    status: 'generated',          // processing | generated
    download_url: 'https://...'  // PDF 下载链接
  },
  msg: ''
}

关键注意事项

⚠️ 1. 金额字段单位必须是"分"

错误示例

// ❌ 错误:直接发送"元"
{
  coverage: 100.00  // 后端会解析错误或精度丢失
}

正确示例

// ✅ 正确:发送"分"
{
  coverage: 10000    // 后端接收后再除以100
}

⚠️ 2. 检查响应码

必须检查 res.code === 1

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

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

const loading = ref(false)

const submit = async () => {
  loading.value = true

  try {
    await submitPlanAPI(params)
  } finally {
    loading.value = false
  }
}

调试技巧

1. 打印请求数据

提交前打印完整数据(已实现):

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)

打印效果

// 格式化后(便于查看)
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 秒

查看请求日志

// 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(浮点数),但后端期望的是整数(分)。

解决方案:确保发送的是整数(分):

// ❌ 错误
form_data: {
  coverage: 100.00  // 浮点数
}

// ✅ 正确
form_data: {
  coverage: 10000   // 整数
}

Q2: 后端返回的金额如何显示?

后端返回的金额单位应该是"分"

// 后端返回
{
  code: 1,
  data: {
    coverage: 10000  // 分
  }
}

// 前端显示
const displayYuan = (res.data.coverage / 100).toFixed(2)
// displayYuan = '100.00'

Q3: 如何验证金额是否正确?

验证方法

// 输入 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

/**
 * 提交计划书表单
 *
 * @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. 查询计划书状态

/**
 * 查询计划书生成状态
 *
 * @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(建议创建)

/**
 * 元转分
 * @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('.')
}

使用示例

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:创建文档,记录金额字段单位规范和联调注意事项

相关文档