## 问题分析 - 组件 `coupon-dialog.vue` 在 `setup` 中使用了: ```ts watch(() => props.data, (newData) => { ... else { resetForm() } }, { immediate: true }) ``` - `resetForm` 在源码中以 `const resetForm = () => { ... }` 形式定义在 `watch` 之后。由于 `immediate: true` 会在初始化阶段立即执行回调,导致在 `resetForm` 尚未初始化之前被调用,抛出 `ReferenceError: Cannot access 'resetForm' before initialization`。 ## 修复方案 1) 将 `resetForm` 改为函数声明并上移到 `watch` 之前: ```ts function resetForm() { form.value = { name:'', coupon_type:1, discount_type:1, discount_value:0, valid_days:30, status:1, remark:'' } } ``` - 函数声明具备提升(hoisting),不会出现“未初始化”问题。 - 位置调整到 `rules` 与 `dialogTitle` 定义之后、`watch(props.data, ...)` 之前。 2) 保留 `immediate: true`(业务期望首次打开时即填充/重置),无需改动;如需更稳健可补充 `flush: 'post'`,但此处核心是函数提升顺序问题。 3) 可选强化 - 如同时监听 `visible`,建议统一在 `watch` 中使用已声明的 `resetForm` 与 `fillFormFromProps(newData)` 两个函数,避免将逻辑直接写在回调内。 - 若依赖 `formRef.resetFields()` 的时机,考虑在 `handleClose` 使用 `nextTick` 保证 DOM 与表单实例可用。 ## 变更清单 - 文件:`web/admin/src/views/operations/coupons/modules/coupon-dialog.vue` - 改动: - 将 `resetForm` 改为函数声明并移动到 `watch` 之前。 - (可选)在 `watch` 的第三参数加入 `flush: 'post'`。 ## 验收 - 打开/切换数据源时不再出现 `ReferenceError`。 - 创建/编辑模式下首次加载和重置行为保持一致(`immediate: true` 生效)。 确认后我将按上述方案修改代码并验证。