| | |
| | | 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点生效' : '领取后生效' |
| | |
| | | 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(() => { |
| | |
| | | </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"> |
| | |
| | | |
| | | <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" /> |