zhuml4
2026-08-07 3915a4ef62f28e76a3fefd67346c2bbffb8d73e1
fix(coupon): 修复优惠券页签标题、tab切换脏数据及添加页生效规则选项

- 页签标题:切换 tab.name 强制 i18n 回退 meta.title,编辑/详情/添加分别显示对应标题
- 修复同页不同 query 的 tab 切换时组件复用导致表单残留上一张券数据的问题
- 添加模式屏蔽「领取后次日0点生效」,仅支持默认的领取后生效
- 清理模板重复/错乱标签,修复 Invalid end tag 编译错误

Co-Authored-By: 祝美莲 <zhuml4@xiaopeng.com>
1个文件已修改
89 ■■■■■ 已修改文件
src/views/userContent/active/coupon/add.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/userContent/active/coupon/add.vue
@@ -32,24 +32,38 @@
  return str || null
})
const formModel = ref({
  code: '',
  name: '',
  type: null,
  conditionAmount: '',
  amount: '',
  amount2: 0,
  amount3: '',
  upperLimit: '',
  description: '',
  effectiveRules: 1 as number,
  expireRulesDays: '',
})
function getInitialFormModel() {
  return {
    code: '',
    name: '',
    type: null,
    conditionAmount: '',
    amount: '',
    amount2: 0,
    amount3: '',
    upperLimit: '',
    description: '',
    effectiveRules: 1 as number,
    expireRulesDays: '',
  }
}
const effectiveRulesOptions = [
  { label: '领取后生效', value: 1 },
  { label: '领取后次日0点生效', value: 2 },
]
const formModel = ref(getInitialFormModel())
function resetFormModel() {
  formModel.value = getInitialFormModel()
}
// 添加模式下屏蔽「领取后次日0点生效」,仅支持默认的领取后生效;编辑/详情保留全部选项以兼容存量数据
const effectiveRulesOptions = computed(() => {
  const options = [
    { label: '领取后生效', value: 1 },
    { label: '领取后次日0点生效', value: 2 },
  ]
  if (!isEditMode.value && !isReadonly.value)
    return options.filter(item => item.value === 1)
  return options
})
const effectiveRulesLabel = computed(() => {
  return Number(formModel.value.effectiveRules) === 2 ? '领取后次日0点生效' : '领取后生效'
@@ -481,17 +495,43 @@
function syncPageTitle() {
  route.meta.title = pageTitle.value
  document.title = pageTitle.value
  const currentMatchedRoute = route.matched[route.matched.length - 1]
  if (currentMatchedRoute) {
    currentMatchedRoute.meta.title = pageTitle.value
  }
  const fullPath = route.fullPath
  tabStore.modifyTab(fullPath, (tab: RouteLocationNormalized) => {
    if (tab)
  const targetTabPaths = [route.fullPath, tabStore.currentTabPath].filter(Boolean)
  targetTabPaths.forEach((fullPath) => {
    if (tabStore.getTabIndex(fullPath) === -1)
      return
    tabStore.modifyTab(fullPath, (tab: RouteLocationNormalized) => {
      if (!tab)
        return
      tab.meta.title = pageTitle.value
      // 标签页文案优先走 route.name 对应的国际化 key,这里切换成一个不存在的 name,
      // 让 TabBar 回退显示 meta.title,从而正确展示当前页面标题
      tab.name = (isReadonly.value ? 'detailCoupon' : isEditMode.value ? 'editCoupon' : 'addCoupon') as never
    })
  })
}
watch(() => route.fullPath, () => {
  syncPageTitle()
}, { immediate: true })
// 布局组件以 route.path 作为组件 key,同页不同 query 的 tab 互相切换时组件实例会被复用,
// 这里监听 fullPath 变化按当前模式重新加载/重置表单,避免展示上一张券的脏数据
watch(() => route.fullPath, async () => {
  formRef.value?.restoreValidation()
  isSelectOpen.value = false
  if ((isEditMode.value || isReadonly.value) && couponId.value) {
    await getDetail()
  }
  else {
    resetFormModel()
  }
  initialSnapshot.value = getSnapshot()
})
onMounted(() => {
  getDetail().finally(() => {
@@ -684,7 +724,6 @@
            </div>
            <div class="form-row full-width">
            <div class="form-row full-width">
              <n-form-item label="生效规则" path="effectiveRules" :required="!isReadonly">
                <template v-if="!isReadonly">
                  <n-radio-group v-model:value="formModel.effectiveRules">
@@ -732,14 +771,6 @@
            <div class="form-row full-width">
              <n-form-item label="优惠券说明" path="description" label-placement="top">
                <div class="w-full rich-text-wrapper">
                  <template v-if="!isReadonly">
                    <AiRichTextEditor v-model="formModel.description" height="300px" :max-length="200" />
                  </template>
                  <div v-else class="rich-text-content" v-html="formModel.description" />
                </div>
              </n-form-item>
            </div>
                <div class="w-full rich-text-wrapper">
                  <template v-if="!isReadonly">
                    <AiRichTextEditor v-model="formModel.description" height="300px" :max-length="200" />