hookehuyr

fix(plan): 修复计划书提交错误信息传递问题

- 移除 fn() 中的自动 toast,避免双重提示
- 扩展 toast 显示时长从 2 秒到 3 秒
- PlanFormContainer emit 时包含 message 字段
- 所有父组件使用 result.message 传递后端错误信息到结果页面
- 修复 index.vue 中硬编码错误消息的问题
...@@ -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)
......