hookehuyr

fix(plan): 修复表单重置不稳定问题

问题描述:
- 提交成功后,有时表单会保留上次的数据
- 表现不稳定:大部分时候正常,偶尔会有残留数据
- 影响用户体验,需要手动清除数据

根本原因:
- 依赖 watch 监听器重置表单存在竞态条件
- watch(visible) 只在弹窗打开时重置,关闭时不重置
- 组件可能被缓存(v-show),状态未清理
- 响应式更新时序问题导致残留

解决方案:
1. 在 submit() 成功后立即调用 resetForm()
2. 在 close() 关闭弹窗前调用 resetForm()
3. 优化 watch(visible) 作为安全网,检测残留数据
4. 为所有模板组件添加 clearErrors() 方法

技术改进:
- 新增 resetForm() 函数:重置表单和错误状态
- submit() 中调用 resetForm(),确保提交后立即清空
- close() 中调用 resetForm(),确保关闭时清空
- watch(visible) 仅在检测到残留数据时才重置
- 统一模板组件接口:validate + clearErrors

影响文件:
- src/components/PlanFormContainer.vue
- src/components/PlanTemplates/SavingsTemplate.vue
- src/components/PlanTemplates/LifeInsuranceTemplate.vue
- src/components/PlanTemplates/CriticalIllnessTemplate.vue

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -164,36 +164,31 @@ const formData = ref({})
const templateRef = ref(null)
/**
* 监听产品变化,重置表单数据
*/
watch(
() => props.product,
(newProduct) => {
if (newProduct) {
// 重置表单数据
formData.value = {}
}
},
{ immediate: true }
)
/**
* 监听显示状态变化,弹窗打开时重置表单
* 监听显示状态变化,弹窗打开时确保表单是干净的
* @description 这是最后的安全网,确保弹窗打开时表单一定是空的
*/
watch(
() => props.visible,
(newVal) => {
if (newVal) {
// 弹窗打开时重置表单
formData.value = {}
if (newVal && Object.keys(formData.value).length > 0) {
// 弹窗打开且表单有数据时,强制重置
console.log('[PlanFormContainer] 弹窗打开时检测到残留数据,强制重置')
resetForm()
}
}
)
/**
* 关闭弹窗
* @description 关闭时重置表单数据,避免下次打开时保留旧数据
*/
const close = () => {
console.log('[PlanFormContainer] 关闭弹窗,重置表单')
// 关闭前重置表单
resetForm()
// 触发关闭事件
emit('close')
}
......@@ -217,11 +212,31 @@ const submit = () => {
form_data: formData.value
})
// 发送提交事件
emit('submit', {
product_id: props.product.id,
form_sn: props.product.form_sn,
form_data: formData.value
})
// ✅ 提交成功后立即重置表单,避免下次打开时保留旧数据
resetForm()
}
/**
* 重置表单数据
* @description 清空表单数据和错误状态
*/
const resetForm = () => {
console.log('[PlanFormContainer] 重置表单数据')
// 重置表单数据
formData.value = {}
// 重置子组件的验证状态(如果有)
if (templateRef.value && templateRef.value.clearErrors) {
templateRef.value.clearErrors()
}
}
</script>
......
......@@ -197,8 +197,19 @@ const validate = () => {
return true
}
/**
* 清除验证错误
* @description 由于使用 Toast 显示错误,无需清除状态
* 保留此方法以保持接口一致性
*/
const clearErrors = () => {
// 当前使用 Toast 显示错误,无需清除错误状态
// 如果将来改用内联错误提示,可以在这里清除错误状态
}
defineExpose({
validate
validate,
clearErrors
})
</script>
......
......@@ -197,8 +197,19 @@ const validate = () => {
return true
}
/**
* 清除验证错误
* @description 由于使用 Toast 显示错误,无需清除状态
* 保留此方法以保持接口一致性
*/
const clearErrors = () => {
// 当前使用 Toast 显示错误,无需清除错误状态
// 如果将来改用内联错误提示,可以在这里清除错误状态
}
defineExpose({
validate
validate,
clearErrors
})
</script>
......
......@@ -461,8 +461,19 @@ const validate = () => {
return true
}
/**
* 清除验证错误
* @description 由于使用 Toast 显示错误,无需清除状态
* 保留此方法以保持接口一致性
*/
const clearErrors = () => {
// 当前使用 Toast 显示错误,无需清除错误状态
// 如果将来改用内联错误提示,可以在这里清除错误状态
}
defineExpose({
validate
validate,
clearErrors
})
</script>
......