fix(plan): 修复计划书提交错误信息传递问题
- 移除 fn() 中的自动 toast,避免双重提示 - 扩展 toast 显示时长从 2 秒到 3 秒 - PlanFormContainer emit 时包含 message 字段 - 所有父组件使用 result.message 传递后端错误信息到结果页面 - 修复 index.vue 中硬编码错误消息的问题
Showing
8 changed files
with
99 additions
and
71 deletions
| ... | @@ -24,14 +24,24 @@ export const fn = (api) => { | ... | @@ -24,14 +24,24 @@ export const fn = (api) => { |
| 24 | if (res_data && res_data.code === 1) { | 24 | if (res_data && res_data.code === 1) { |
| 25 | return res_data | 25 | return res_data |
| 26 | } | 26 | } |
| 27 | - // 失败兜底:优先返回后端响应,同时做 toast 提示 | 27 | + // 失败兜底:返回后端响应,由调用方统一处理 toast 提示 |
| 28 | console.warn('接口请求失败:', res) | 28 | console.warn('接口请求失败:', res) |
| 29 | if (res_data && res_data.show === false) return res_data | 29 | if (res_data && res_data.show === false) return res_data |
| 30 | - Taro.showToast({ | 30 | + |
| 31 | - title: (res_data && res_data.msg) ? res_data.msg : '请求失败', | 31 | + // 🔍 调试:打印 res_data 的详细内容 |
| 32 | - icon: 'none', | 32 | + console.log('[fn] res_data:', res_data) |
| 33 | - duration: 2000 | 33 | + console.log('[fn] res_data.code:', res_data?.code) |
| 34 | - }) | 34 | + console.log('[fn] res_data.msg:', res_data?.msg) |
| 35 | + console.log('[fn] res_data.data:', res_data?.data) | ||
| 36 | + | ||
| 37 | + // ❌ 移除自动 toast,避免双重提示 | ||
| 38 | + // Taro.showToast({ | ||
| 39 | + // title: (res_data && res_data.msg) ? res_data.msg : '请求失败', | ||
| 40 | + // icon: 'none', | ||
| 41 | + // duration: 2000 | ||
| 42 | + // }) | ||
| 43 | + | ||
| 44 | + // 返回:如果是 res_data 就返回,否则返回兜底对象 | ||
| 35 | return res_data || { code: 0, data: null, msg: '请求失败' } | 45 | return res_data || { code: 0, data: null, msg: '请求失败' } |
| 36 | }) | 46 | }) |
| 37 | .catch(err => { | 47 | .catch(err => { | ... | ... |
| ... | @@ -486,9 +486,13 @@ const onConfirm = () => { | ... | @@ -486,9 +486,13 @@ const onConfirm = () => { |
| 486 | // 将元转换为分,保留两位小数 | 486 | // 将元转换为分,保留两位小数 |
| 487 | let yuan = parseFloat(inputValue.value || '0') | 487 | let yuan = parseFloat(inputValue.value || '0') |
| 488 | if (!Number.isNaN(yuan)) { | 488 | if (!Number.isNaN(yuan)) { |
| 489 | - // 先保留两位小数,再转换为分 | 489 | + // 先保留两位小数(字符串形式),再转换为分 |
| 490 | - const formattedYuan = parseFloat(yuan.toFixed(2)) | 490 | + // 使用 toFixed(2) 确保留两位小数,然后 * 100 并四舍五入 |
| 491 | - const cents = Math.round(formattedYuan * 100) | 491 | + const formattedYuanStr = yuan.toFixed(2) |
| 492 | + const cents = Math.round(parseFloat(formattedYuanStr) * 100) | ||
| 493 | + | ||
| 494 | + // 调试日志(可以移除) | ||
| 495 | + console.log('[AmountKeyboard] 输入值:', inputValue.value, '元:', yuan, '格式化:', formattedYuanStr, '分:', cents) | ||
| 492 | 496 | ||
| 493 | emit('update:modelValue', cents) | 497 | emit('update:modelValue', cents) |
| 494 | } | 498 | } | ... | ... |
| ... | @@ -234,7 +234,7 @@ const submit = async () => { | ... | @@ -234,7 +234,7 @@ const submit = async () => { |
| 234 | Taro.showToast({ | 234 | Taro.showToast({ |
| 235 | title: '产品数据为空', | 235 | title: '产品数据为空', |
| 236 | icon: 'none', | 236 | icon: 'none', |
| 237 | - duration: 2000 | 237 | + duration: 3000 |
| 238 | }) | 238 | }) |
| 239 | return false | 239 | return false |
| 240 | } | 240 | } |
| ... | @@ -281,7 +281,14 @@ const submit = async () => { | ... | @@ -281,7 +281,14 @@ const submit = async () => { |
| 281 | 281 | ||
| 282 | if (apiField) { | 282 | if (apiField) { |
| 283 | // 有映射:使用映射后的字段名 | 283 | // 有映射:使用映射后的字段名 |
| 284 | + // 特殊处理:coverage(分)需要转换为元 | ||
| 285 | + if (key === 'coverage') { | ||
| 286 | + const coverageInYuan = (formData.value[key] / 100).toFixed(2) | ||
| 287 | + console.log(`[PlanFormContainer] coverage 转换: ${key} (${formData.value[key]} 分) → ${apiField} (${coverageInYuan} 元)`) | ||
| 288 | + requestData[apiField] = coverageInYuan | ||
| 289 | + } else { | ||
| 284 | requestData[apiField] = formData.value[key] | 290 | requestData[apiField] = formData.value[key] |
| 291 | + } | ||
| 285 | } else if (key === 'total_amount') { | 292 | } else if (key === 'total_amount') { |
| 286 | // 特殊处理:总保费(分 → 元) | 293 | // 特殊处理:总保费(分 → 元) |
| 287 | requestData.total_premium = (formData.value[key] / 100).toFixed(2) | 294 | requestData.total_premium = (formData.value[key] / 100).toFixed(2) |
| ... | @@ -311,7 +318,7 @@ const submit = async () => { | ... | @@ -311,7 +318,7 @@ const submit = async () => { |
| 311 | Taro.showToast({ | 318 | Taro.showToast({ |
| 312 | title: '提交成功', | 319 | title: '提交成功', |
| 313 | icon: 'success', | 320 | icon: 'success', |
| 314 | - duration: 2000 | 321 | + duration: 3000 |
| 315 | }) | 322 | }) |
| 316 | 323 | ||
| 317 | // 发送提交成功事件(携带 order_id) | 324 | // 发送提交成功事件(携带 order_id) |
| ... | @@ -326,18 +333,28 @@ const submit = async () => { | ... | @@ -326,18 +333,28 @@ const submit = async () => { |
| 326 | } else { | 333 | } else { |
| 327 | Taro.hideLoading() | 334 | Taro.hideLoading() |
| 328 | 335 | ||
| 336 | + // 🔍 调试:完整响应数据 | ||
| 337 | + console.log('[PlanFormContainer] API 完整响应:', res) | ||
| 338 | + console.log('[PlanFormContainer] res.data:', res.data) | ||
| 339 | + console.log('[PlanFormContainer] res.msg:', res.msg) | ||
| 340 | + console.log('[PlanFormContainer] res.data?.msg:', res.data?.msg) | ||
| 341 | + | ||
| 329 | // 失败时,尝试从 res.data 或 res.msg 中获取错误信息 | 342 | // 失败时,尝试从 res.data 或 res.msg 中获取错误信息 |
| 343 | + // 注意:fn() 函数会将 res.data 设置为 null,但 res.msg 保留了 | ||
| 330 | const errorMsg = res.data?.msg || res.msg || '提交失败,请稍后重试' | 344 | const errorMsg = res.data?.msg || res.msg || '提交失败,请稍后重试' |
| 331 | 345 | ||
| 346 | + console.log('[PlanFormContainer] 最终错误信息:', errorMsg) | ||
| 347 | + | ||
| 332 | Taro.showToast({ | 348 | Taro.showToast({ |
| 333 | title: errorMsg, | 349 | title: errorMsg, |
| 334 | icon: 'none', | 350 | icon: 'none', |
| 335 | - duration: 2000 | 351 | + duration: 3000 |
| 336 | }) | 352 | }) |
| 337 | 353 | ||
| 338 | - // 返回失败结果(不包含 order_id) | 354 | + // 返回失败结果,传递错误信息给父组件 |
| 339 | emit('submit', { | 355 | emit('submit', { |
| 340 | - success: false | 356 | + success: false, |
| 357 | + message: errorMsg | ||
| 341 | }) | 358 | }) |
| 342 | 359 | ||
| 343 | return false | 360 | return false |
| ... | @@ -350,7 +367,7 @@ const submit = async () => { | ... | @@ -350,7 +367,7 @@ const submit = async () => { |
| 350 | Taro.showToast({ | 367 | Taro.showToast({ |
| 351 | title: '网络异常,请重试', | 368 | title: '网络异常,请重试', |
| 352 | icon: 'none', | 369 | icon: 'none', |
| 353 | - duration: 2000 | 370 | + duration: 3000 |
| 354 | }) | 371 | }) |
| 355 | 372 | ||
| 356 | return false | 373 | return false | ... | ... |
| ... | @@ -85,17 +85,28 @@ | ... | @@ -85,17 +85,28 @@ |
| 85 | 85 | ||
| 86 | <!-- 指定提取金额模式 --> | 86 | <!-- 指定提取金额模式 --> |
| 87 | <template v-if="form.withdrawal_mode === '指定提取金额'"> | 87 | <template v-if="form.withdrawal_mode === '指定提取金额'"> |
| 88 | - <!-- 按年岁/按保单年度选择 --> | 88 | + <!-- 提取方式:只有按年岁 --> |
| 89 | <PlanFieldRadio | 89 | <PlanFieldRadio |
| 90 | v-model="form.specified_amount_type" | 90 | v-model="form.specified_amount_type" |
| 91 | label="提取方式" | 91 | label="提取方式" |
| 92 | - :options="['按年岁', '按保单年度']" | 92 | + :options="['按年岁']" |
| 93 | :required="true" | 93 | :required="true" |
| 94 | class="mb-5" | 94 | class="mb-5" |
| 95 | /> | 95 | /> |
| 96 | 96 | ||
| 97 | <!-- 按年岁 --> | 97 | <!-- 按年岁 --> |
| 98 | <template v-if="form.specified_amount_type === '按年岁'"> | 98 | <template v-if="form.specified_amount_type === '按年岁'"> |
| 99 | + <!-- 提取金额币种(只读) --> | ||
| 100 | + <div class="mb-5"> | ||
| 101 | + <div class="text-sm text-gray-600 mb-2 flex items-center"> | ||
| 102 | + <span class="text-red-500 mr-1">*</span> | ||
| 103 | + <span>提取金额币种</span> | ||
| 104 | + </div> | ||
| 105 | + <div class="px-4 py-3 bg-gray-50 rounded-lg border border-gray-200"> | ||
| 106 | + <span class="text-gray-900">{{ currencyLabel }}</span> | ||
| 107 | + </div> | ||
| 108 | + </div> | ||
| 109 | + | ||
| 99 | <!-- 由几岁开始 --> | 110 | <!-- 由几岁开始 --> |
| 100 | <PlanFieldAgePicker | 111 | <PlanFieldAgePicker |
| 101 | v-model="form.withdrawal_start_age" | 112 | v-model="form.withdrawal_start_age" |
| ... | @@ -129,28 +140,6 @@ | ... | @@ -129,28 +140,6 @@ |
| 129 | /> | 140 | /> |
| 130 | </div> | 141 | </div> |
| 131 | </template> | 142 | </template> |
| 132 | - | ||
| 133 | - <!-- 按保单年度 --> | ||
| 134 | - <template v-if="form.specified_amount_type === '按保单年度'"> | ||
| 135 | - <!-- 由几岁开始 --> | ||
| 136 | - <PlanFieldAgePicker | ||
| 137 | - v-model="form.withdrawal_start_age" | ||
| 138 | - label="由几岁开始" | ||
| 139 | - placeholder="请输入开始提取年龄" | ||
| 140 | - :required="true" | ||
| 141 | - class="mb-5" | ||
| 142 | - /> | ||
| 143 | - | ||
| 144 | - <!-- 提取期(年) --> | ||
| 145 | - <PlanFieldSelect | ||
| 146 | - v-model="form.withdrawal_period" | ||
| 147 | - label="提取期(年)" | ||
| 148 | - placeholder="请选择提取期" | ||
| 149 | - :options="withdrawalPeriods" | ||
| 150 | - :required="true" | ||
| 151 | - class="mb-5" | ||
| 152 | - /> | ||
| 153 | - </template> | ||
| 154 | </template> | 143 | </template> |
| 155 | 144 | ||
| 156 | <!-- 最高固定提取金额模式 --> | 145 | <!-- 最高固定提取金额模式 --> |
| ... | @@ -282,7 +271,8 @@ const initializeForm = (value) => { | ... | @@ -282,7 +271,8 @@ const initializeForm = (value) => { |
| 282 | // 默认值 | 271 | // 默认值 |
| 283 | withdrawal_enabled: value.withdrawal_enabled || '否', | 272 | withdrawal_enabled: value.withdrawal_enabled || '否', |
| 284 | withdrawal_mode: value.withdrawal_mode || '指定提取金额', | 273 | withdrawal_mode: value.withdrawal_mode || '指定提取金额', |
| 285 | - specified_amount_type: value.specified_amount_type || '按年岁' | 274 | + specified_amount_type: value.specified_amount_type || '按年岁', |
| 275 | + withdrawal_currency: value.withdrawal_currency || props.config?.withdrawal_plan?.default_currency || 'HKD' | ||
| 286 | }) | 276 | }) |
| 287 | } | 277 | } |
| 288 | 278 | ||
| ... | @@ -313,7 +303,8 @@ watch( | ... | @@ -313,7 +303,8 @@ watch( |
| 313 | // 默认值 | 303 | // 默认值 |
| 314 | withdrawal_enabled: newVal.withdrawal_enabled || '否', | 304 | withdrawal_enabled: newVal.withdrawal_enabled || '否', |
| 315 | withdrawal_mode: newVal.withdrawal_mode || '指定提取金额', | 305 | withdrawal_mode: newVal.withdrawal_mode || '指定提取金额', |
| 316 | - specified_amount_type: newVal.specified_amount_type || '按年岁' | 306 | + specified_amount_type: newVal.specified_amount_type || '按年岁', |
| 307 | + withdrawal_currency: newVal.withdrawal_currency || props.config?.withdrawal_plan?.default_currency || 'HKD' | ||
| 317 | }) | 308 | }) |
| 318 | previousModelValue = newVal | 309 | previousModelValue = newVal |
| 319 | } | 310 | } |
| ... | @@ -331,11 +322,19 @@ watch( | ... | @@ -331,11 +322,19 @@ watch( |
| 331 | ) | 322 | ) |
| 332 | 323 | ||
| 333 | /** | 324 | /** |
| 334 | - * 默认币种(从配置读取) | 325 | + * 提取金额币种标签(用于显示) |
| 335 | * @type {ComputedRef<string>} | 326 | * @type {ComputedRef<string>} |
| 327 | + * @description 显示币种的完整名称,如"港币 HKD" | ||
| 336 | */ | 328 | */ |
| 337 | -const defaultCurrency = computed(() => { | 329 | +const currencyLabel = computed(() => { |
| 338 | - return props.config?.withdrawal_plan?.default_currency || 'HKD' | 330 | + const currencyCode = props.config?.withdrawal_plan?.default_currency || 'HKD' |
| 331 | + const currencyNames = { | ||
| 332 | + 'HKD': '港币', | ||
| 333 | + 'USD': '美元', | ||
| 334 | + 'CNY': '人民币', | ||
| 335 | + 'EUR': '欧元' | ||
| 336 | + } | ||
| 337 | + return `${currencyNames[currencyCode] || currencyCode} ${currencyCode}` | ||
| 339 | }) | 338 | }) |
| 340 | 339 | ||
| 341 | /** | 340 | /** |
| ... | @@ -367,28 +366,15 @@ const onWithdrawalModeChange = (mode) => { | ... | @@ -367,28 +366,15 @@ const onWithdrawalModeChange = (mode) => { |
| 367 | if (mode === '最高固定提取金额') { | 366 | if (mode === '最高固定提取金额') { |
| 368 | // 最高固定金额模式不需要指定金额的相关字段 | 367 | // 最高固定金额模式不需要指定金额的相关字段 |
| 369 | delete form.specified_amount_type | 368 | delete form.specified_amount_type |
| 369 | + delete form.withdrawal_currency | ||
| 370 | delete form.annual_amount | 370 | delete form.annual_amount |
| 371 | delete form.increase_rate | 371 | delete form.increase_rate |
| 372 | } else if (mode === '指定提取金额') { | 372 | } else if (mode === '指定提取金额') { |
| 373 | - // 指定提取金额模式,等待用户选择按年岁或按保单年度 | 373 | + // 指定提取金额模式(按年岁),保留现有字段 |
| 374 | - // 保留现有字段 | ||
| 375 | } | 374 | } |
| 376 | } | 375 | } |
| 377 | 376 | ||
| 378 | /** | 377 | /** |
| 379 | - * 监听指定提取金额方式变化 | ||
| 380 | - * @description 当用户在"按年岁"和"按保单年度"之间切换时,清理不相关字段 | ||
| 381 | - */ | ||
| 382 | -watch( | ||
| 383 | - () => form.specified_amount_type, | ||
| 384 | - (newType) => { | ||
| 385 | - // 两种方式都不需要 annual_amount 和 increase_rate(小程序端不需要) | ||
| 386 | - delete form.annual_amount | ||
| 387 | - delete form.increase_rate | ||
| 388 | - } | ||
| 389 | -) | ||
| 390 | - | ||
| 391 | -/** | ||
| 392 | * 监听提取计划启用状态变化 | 378 | * 监听提取计划启用状态变化 |
| 393 | * @description 当用户选择"否"时,清除所有提取计划相关字段 | 379 | * @description 当用户选择"否"时,清除所有提取计划相关字段 |
| 394 | */ | 380 | */ |
| ... | @@ -399,6 +385,7 @@ watch( | ... | @@ -399,6 +385,7 @@ watch( |
| 399 | // 清除所有提取计划相关字段 | 385 | // 清除所有提取计划相关字段 |
| 400 | delete form.withdrawal_mode | 386 | delete form.withdrawal_mode |
| 401 | delete form.specified_amount_type | 387 | delete form.specified_amount_type |
| 388 | + delete form.withdrawal_currency | ||
| 402 | delete form.withdrawal_start_age | 389 | delete form.withdrawal_start_age |
| 403 | delete form.withdrawal_period | 390 | delete form.withdrawal_period |
| 404 | delete form.annual_amount | 391 | delete form.annual_amount |
| ... | @@ -468,6 +455,10 @@ const validate = () => { | ... | @@ -468,6 +455,10 @@ const validate = () => { |
| 468 | } | 455 | } |
| 469 | 456 | ||
| 470 | if (form.specified_amount_type === '按年岁') { | 457 | if (form.specified_amount_type === '按年岁') { |
| 458 | + if (!form.withdrawal_currency) { | ||
| 459 | + Taro.showToast({ title: '请选择提取金额币种', icon: 'none' }) | ||
| 460 | + return false | ||
| 461 | + } | ||
| 471 | if (form.increase_rate === undefined || form.increase_rate === '') { | 462 | if (form.increase_rate === undefined || form.increase_rate === '') { |
| 472 | Taro.showToast({ title: '请输入每年递增提取之百分比', icon: 'none' }) | 463 | Taro.showToast({ title: '请输入每年递增提取之百分比', icon: 'none' }) |
| 473 | return false | 464 | return false | ... | ... |
| ... | @@ -243,9 +243,9 @@ const handlePlanSubmit = (result) => { | ... | @@ -243,9 +243,9 @@ const handlePlanSubmit = (result) => { |
| 243 | success: result.success ? 'true' : 'false' | 243 | success: result.success ? 'true' : 'false' |
| 244 | }; | 244 | }; |
| 245 | 245 | ||
| 246 | - // 失败时可以传递错误信息(可选) | 246 | + // 失败时传递后端返回的错误信息 |
| 247 | - if (!result.success) { | 247 | + if (!result.success && result.message) { |
| 248 | - params.message = '提交失败,请稍后重试'; | 248 | + params.message = result.message; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 | 251 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 | ... | ... |
| ... | @@ -520,11 +520,13 @@ const handlePlanSubmit = (result) => { | ... | @@ -520,11 +520,13 @@ const handlePlanSubmit = (result) => { |
| 520 | success: result.success ? 'true' : 'false' | 520 | success: result.success ? 'true' : 'false' |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | - // 失败时可以传递错误信息(可选) | 523 | + // 失败时传递后端返回的错误信息 |
| 524 | - if (!result.success) { | 524 | + if (!result.success && result.message) { |
| 525 | - params.message = '提交失败,请稍后重试' | 525 | + params.message = result.message |
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | + console.log('[Product Center] 跳转到结果页面,参数:', params) | ||
| 529 | + | ||
| 528 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 | 530 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 |
| 529 | setTimeout(() => { | 531 | setTimeout(() => { |
| 530 | Taro.navigateTo({ | 532 | Taro.navigateTo({ | ... | ... |
| ... | @@ -239,11 +239,13 @@ const handlePlanSubmit = (result) => { | ... | @@ -239,11 +239,13 @@ const handlePlanSubmit = (result) => { |
| 239 | success: result.success ? 'true' : 'false' | 239 | success: result.success ? 'true' : 'false' |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | - // 失败时可以传递错误信息(可选) | 242 | + // 失败时传递后端返回的错误信息 |
| 243 | - if (!result.success) { | 243 | + if (!result.success && result.message) { |
| 244 | - params.message = '提交失败,请稍后重试' | 244 | + params.message = result.message |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | + console.log('[Product Detail] 跳转到结果页面,参数:', params) | ||
| 248 | + | ||
| 247 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 | 249 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 |
| 248 | setTimeout(() => { | 250 | setTimeout(() => { |
| 249 | Taro.navigateTo({ | 251 | Taro.navigateTo({ | ... | ... |
| ... | @@ -480,11 +480,13 @@ const handlePlanSubmit = (result) => { | ... | @@ -480,11 +480,13 @@ const handlePlanSubmit = (result) => { |
| 480 | success: result.success ? 'true' : 'false' | 480 | success: result.success ? 'true' : 'false' |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | - // 失败时可以传递错误信息(可选) | 483 | + // 失败时传递后端返回的错误信息 |
| 484 | - if (!result.success) { | 484 | + if (!result.success && result.message) { |
| 485 | - params.message = '提交失败,请稍后重试' | 485 | + params.message = result.message |
| 486 | } | 486 | } |
| 487 | 487 | ||
| 488 | + console.log('[Search Page] 跳转到结果页面,参数:', params) | ||
| 489 | + | ||
| 488 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 | 490 | // 延迟跳转,确保 PlanFormContainer 的 toast 显示完毕 |
| 489 | setTimeout(() => { | 491 | setTimeout(() => { |
| 490 | go('/pages/plan-submit-result/index', params) | 492 | go('/pages/plan-submit-result/index', params) | ... | ... |
-
Please register or login to post a comment