| | |
| | | import { addCouponActivity, fetchCouponActivityDetail, fetchCouponDetail } from '@/service/api/coupon' |
| | | import { fetchWhitelistDetail } from '@/service/api/whitelist' |
| | | import { customUploadRequest } from '@/utils/upload' |
| | | import deleteIcon from '@/assets/pricingManagement/delete.svg' |
| | | |
| | | const route = useRoute() |
| | | const router = useRouter() |
| | |
| | | const currentSelectGroupIndex = ref(-1) |
| | | |
| | | const showUserTypeHelpModal = ref(false) |
| | | const strategyList = ref<StrategyItem[]>([createStrategy()]) |
| | | |
| | | function handleOpenCouponModal(strategyIndex: number, type: 'normal' | 'afterUse') { |
| | | currentSelectStrategyIndex.value = strategyIndex |
| | |
| | | showUserModal.value = true |
| | | } |
| | | |
| | | type UserListItem = { |
| | | interface UserListItem { |
| | | id: number | string |
| | | account: string |
| | | remark: string |
| | | } |
| | | |
| | | type UserGroupItem = { |
| | | interface UserGroupItem { |
| | | actitcityId: number | null |
| | | actitcityStrategeId: number | null |
| | | id: number | null |
| | |
| | | |
| | | // 用户群相关 |
| | | const userGroupList = ref<UserGroupItem[]>([ |
| | | { |
| | | ...createUserGroup(5), |
| | | userList: [ |
| | | { id: 1, account: '15708179461', remark: '媒体' }, |
| | | { id: 2, account: '15708179461', remark: '-' }, |
| | | { id: 3, account: '15708179461', remark: '媒体' }, |
| | | { id: 4, account: '15708179461', remark: '-' }, |
| | | { id: 5, account: '15708179461', remark: '-' }, |
| | | ], |
| | | pagination: { page: 1, pageSize: 10, total: 1000 }, |
| | | }, |
| | | createUserGroup(2), |
| | | createUserGroup(1), |
| | | ]) |
| | | |
| | | function handleSaveUsers(rows: any[]) { |
| | |
| | | message.success(`成功导入了 ${newUsers.length} 名用户`) |
| | | } |
| | | |
| | | const activeTab = ref(2) |
| | | const activeTab = ref(4) |
| | | const isEditMode = computed(() => route.query.mode === 'edit' && !!route.query.id) |
| | | |
| | | type UsagePeriodItem = { |
| | | interface UsagePeriodItem { |
| | | startTime: string | null |
| | | endTime: string | null |
| | | } |
| | | |
| | | type DistributionRulesAfterUse = { |
| | | interface DistributionRulesAfterUse { |
| | | ruleType: 1 | 2 |
| | | couponList: any[] |
| | | } |
| | | |
| | | type StrategyItem = { |
| | | interface StrategyItem { |
| | | actitcityId: number | null |
| | | id: number | null |
| | | name: string |
| | | distributionRules: 1 | 2 | 3 |
| | | distributionRulesAfterUse: DistributionRulesAfterUse |
| | | effectRule: '领取后生效' | '领取后指定日期生效' |
| | | effectRule: 1 | 2 |
| | | effectDate: number | null |
| | | distributionsTotal: number | null |
| | | effectiveDays: number | null |
| | |
| | | ruleType: 1, |
| | | couponList: [], |
| | | }, |
| | | effectRule: '领取后生效', |
| | | effectRule: 1, |
| | | effectDate: null, |
| | | distributionsTotal: null, |
| | | effectiveDays: null, |
| | |
| | | couponList: [], |
| | | } |
| | | } |
| | | |
| | | const strategyList = ref<StrategyItem[]>([createStrategy()]) |
| | | |
| | | const strategyGroupOptions = computed(() => { |
| | | return strategyList.value.map((strategy, index) => ({ |
| | |
| | | |
| | | type NotifyTimingValue = 1 | 2 | 4 |
| | | |
| | | type NotifyFormModel = { |
| | | interface NotifyFormModel { |
| | | activityId: number | null |
| | | id: number | null |
| | | noticeType: NotifyTimingValue[] |
| | |
| | | const strategySource = toArray(detail.strategy) |
| | | strategyList.value = strategySource.length |
| | | ? strategySource.map((item: any) => ({ |
| | | actitcityId: item.actitcityId ?? currentActivityId.value, |
| | | id: item.id ?? null, |
| | | name: item.name || '', |
| | | distributionRules: Number(item.distributionRules) as 1 | 2 | 3 || 1, |
| | | distributionRulesAfterUse: parseDistributionRulesAfterUse(item.distributionRulesAfterUse), |
| | | effectRule: '领取后生效', |
| | | effectDate: null, |
| | | distributionsTotal: item.distributionsTotal ?? null, |
| | | effectiveDays: item.effectiveDays ?? null, |
| | | effectiveRules: Number(item.effectiveRules) as 1 | 2 | 3 || 1, |
| | | endTime: item.endTime ? new Date(item.endTime).getTime() : null, |
| | | limitNumber: item.limitNumber ?? 1, |
| | | stackedUsage: Number(item.stackedUsage) as 0 | 1 || 0, |
| | | startUsing: Number(item.startUsing) as 0 | 1 || 0, |
| | | usagePeriod: parseUsagePeriod(item.usagePeriod), |
| | | couponList: toArray(item.couponIds).map((id: number | string) => ({ |
| | | id, |
| | | couponName: `优惠券${id}`, |
| | | })), |
| | | })) |
| | | actitcityId: item.actitcityId ?? currentActivityId.value, |
| | | id: item.id ?? null, |
| | | name: item.name || '', |
| | | distributionRules: Number(item.distributionRules) as 1 | 2 | 3 || 1, |
| | | distributionRulesAfterUse: parseDistributionRulesAfterUse(item.distributionRulesAfterUse), |
| | | effectRule: item.effectRule || 1, |
| | | effectDate: null, |
| | | distributionsTotal: item.distributionsTotal ?? null, |
| | | effectiveDays: item.effectiveDays ?? null, |
| | | effectiveRules: Number(item.effectiveRules) as 1 | 2 | 3 || 1, |
| | | endTime: item.endTime ? new Date(item.endTime).getTime() : null, |
| | | limitNumber: item.limitNumber ?? 1, |
| | | stackedUsage: Number(item.stackedUsage) as 0 | 1 || 0, |
| | | startUsing: Number(item.startUsing) as 0 | 1 || 0, |
| | | usagePeriod: parseUsagePeriod(item.usagePeriod), |
| | | couponList: toArray(item.couponIds).map((id: number | string) => ({ |
| | | id, |
| | | couponName: `优惠券${id}`, |
| | | })), |
| | | })) |
| | | : [createStrategy()] |
| | | |
| | | const userSource = toArray(detail.activityUser) |
| | | userGroupList.value = userSource.length |
| | | ? userSource.map((item: any) => ({ |
| | | actitcityId: item.actitcityId ?? currentActivityId.value, |
| | | actitcityStrategeId: item.actitcityStrategeId ?? null, |
| | | id: item.id ?? null, |
| | | strategyName: item.strategyName || '', |
| | | userList: parseUserList(item.userList), |
| | | userType: Number(item.userType) as 1 | 2 | 3 | 4 | 5 || 1, |
| | | pagination: { page: 1, pageSize: 10, total: toArray(item.userList).length }, |
| | | })) |
| | | actitcityId: item.actitcityId ?? currentActivityId.value, |
| | | actitcityStrategeId: item.actitcityStrategeId ?? null, |
| | | id: item.id ?? null, |
| | | strategyName: item.strategyName || '', |
| | | userList: parseUserList(item.userList), |
| | | userType: Number(item.userType) as 1 | 2 | 3 | 4 | 5 || 1, |
| | | pagination: { page: 1, pageSize: 10, total: toArray(item.userList).length }, |
| | | })) |
| | | : [createUserGroup()] |
| | | |
| | | const notice = detail.notice || {} |
| | |
| | | activeTab.value++ |
| | | } |
| | | |
| | | function handleRemoveUserGroup(index: number) { |
| | | userGroupList.value.splice(index, 1) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getDetail() |
| | | }) |
| | |
| | | <template> |
| | | <div class=" w-full h-full relative content flex flex-col"> |
| | | <div class="p-12px main flex flex-col flex-1 overflow-hidden"> |
| | | <NTabs v-model:value="activeTab" type="line" class="mb-8px custom-tabs" animated> |
| | | <NTabs v-model:value="activeTab" type="line" class="custom-tabs" animated> |
| | | <NTabPane :name="1" tab="活动介绍内容" /> |
| | | <NTabPane :name="2" tab="活动策略配置" /> |
| | | <NTabPane :name="3" tab="发放用户" /> |
| | |
| | | </NForm> |
| | | |
| | | <!-- 活动策略配置 --> |
| | | <div v-show="activeTab === 2"> |
| | | <div v-show="activeTab === 2" class="flex flex-col"> |
| | | <div |
| | | v-for="(strategy, strategyIndex) in strategyList" :key="strategyIndex" |
| | | class="mb-24px pb-24px border-b border-[#EBEEF5] last:border-b-0 last:pb-0 last:mb-0" |
| | | class="mb-12px p-24px pb-12px border border-[#EEE9E9] last:mb-0 rounded-6px" |
| | | > |
| | | <div |
| | | v-if="strategyList.length > 1" |
| | | class="flex justify-between items-center mb-16px bg-[#f5f7fa] p-12px rounded-4px" |
| | | > |
| | | <span class="text-14px font-bold text-[#171f26]">策略 {{ strategyIndex + 1 }}</span> |
| | | <NButton text type="error" @click="handleRemoveStrategy(strategyIndex)"> |
| | | 删除策略 |
| | | </NButton> |
| | | </div> |
| | | |
| | | <NForm :model="strategy" :rules="strategyRules" label-placement="left" require-mark-placement="left"> |
| | | <!-- 策略名称 --> |
| | | <NFormItem label="策略名称:" path="name"> |
| | | <NInput |
| | | v-model:value="strategy.name" placeholder="请输入" maxlength="20" clearable |
| | | style="width: 400px" |
| | | /> |
| | | </NFormItem> |
| | | <div class="flex items-center justify-between mb-16px"> |
| | | <!-- 策略名称 --> |
| | | <NFormItem label="策略名称" path="name"> |
| | | <NInput |
| | | v-model:value="strategy.name" placeholder="请输入" maxlength="20" clearable |
| | | style="width: 300px" |
| | | /> |
| | | </NFormItem> |
| | | <img v-if="strategyList.length > 1" :src="deleteIcon" alt="删除" style="width: 16px;height: 16px;cursor: pointer;" @click="handleRemoveStrategy(strategyIndex)"> |
| | | </div> |
| | | |
| | | <!-- 优惠券 --> |
| | | <NFormItem label="优惠券:"> |
| | | <div class="w-full flex flex-col gap-12px"> |
| | | <NButton type="primary" class="w-120px" @click="handleOpenCouponModal(strategyIndex, 'normal')"> |
| | | 选择任意券 |
| | | <NFormItem label="优惠券"> |
| | | <div class="w-full flex justify-end"> |
| | | <NButton type="primary" style="border: 1px solid #7ABDFF;" secondary class="w-97px" @click="handleOpenCouponModal(strategyIndex, 'normal')"> |
| | | 选择优惠券 |
| | | </NButton> |
| | | <div class="border border-[#EBEEF5] rounded-4px overflow-hidden"> |
| | | <NDataTable |
| | | :columns="createCouponColumns(strategyIndex, 'normal')" |
| | | :data="strategy.couponList" |
| | | :bordered="false" |
| | | size="small" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </NFormItem> |
| | | <div class="mt-4px min-h-[262px]"> |
| | | <NDataTable |
| | | :columns="createCouponColumns(strategyIndex, 'normal')" |
| | | :data="strategy.couponList" |
| | | :bordered="false" |
| | | style="min-height: 263px" |
| | | flex-height |
| | | :pagination="false" |
| | | > |
| | | <template #empty> |
| | | <div class="flex-center"> |
| | | <img src="/src/assets/element-img/no-data.png" style="width:123px;height:125px" @error="(e: any) => { e.target.src = 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png' }"> |
| | | </div> |
| | | </template> |
| | | </NDataTable> |
| | | </div> |
| | | |
| | | <!-- 发放规则 --> |
| | | <NFormItem label="发放规则:"> |
| | | <div class="flex flex-col gap-16px w-full"> |
| | | <NRadioGroup v-model:value="strategy.distributionRules"> |
| | | <NFormItem label="发放规则" class="mt-24px"> |
| | | <div class="w-full pl-8px"> |
| | | <NRadioGroup v-model:value="strategy.distributionRules" class="h-32px flex items-center"> |
| | | <NSpace> |
| | | <NRadio :value="1" label="每日0点循环发放" /> |
| | | <NRadio :value="1" label="每日循环发放" /> |
| | | <NRadio :value="2" label="仅发放一次" /> |
| | | <NRadio :value="3" label="使用后发放" /> |
| | | </NSpace> |
| | |
| | | |
| | | <div |
| | | v-if="strategy.distributionRules === 3" |
| | | class="bg-[#FAFAFA] p-16px rounded-4px border border-[#EBEEF5] flex flex-col gap-16px w-full" |
| | | class="flex flex-col gap-16px w-full mt-8px" |
| | | > |
| | | <div class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">使用后发放规则:</span> |
| | | <span>使用后发放规则</span> |
| | | <NRadioGroup v-model:value="strategy.distributionRulesAfterUse.ruleType"> |
| | | <NSpace> |
| | | <NRadio :value="1" label="本券使用后循环发放" /> |
| | |
| | | </NRadioGroup> |
| | | </div> |
| | | <div v-if="strategy.distributionRulesAfterUse.ruleType === 2" class="flex flex-col gap-12px w-full"> |
| | | <div class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">优惠券:</span> |
| | | <div class="flex items-center justify-between gap-16px"> |
| | | <span>优惠券</span> |
| | | <NButton |
| | | type="primary" class="w-120px" |
| | | type="primary" secondary style="border: 1px solid #7ABDFF;" class="w-97px" |
| | | @click="handleOpenCouponModal(strategyIndex, 'afterUse')" |
| | | > |
| | | 选择优惠券 |
| | | </NButton> |
| | | </div> |
| | | <div class="border border-[#EBEEF5] rounded-4px overflow-hidden w-full"> |
| | | <div class="overflow-hidden w-full"> |
| | | <NDataTable |
| | | :columns="createCouponColumns(strategyIndex, 'afterUse')" |
| | | :data="strategy.distributionRulesAfterUse.couponList" |
| | | :bordered="false" |
| | | size="small" |
| | | /> |
| | | style="min-height: 263px" |
| | | flex-height |
| | | :pagination="false" |
| | | > |
| | | <template #empty> |
| | | <div class="flex-center"> |
| | | <img src="/src/assets/element-img/no-data.png" style="width:123px;height:125px" @error="(e: any) => { e.target.src = 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png' }"> |
| | | </div> |
| | | </template> |
| | | </NDataTable> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </NFormItem> |
| | | |
| | | <!-- 生效规则 --> |
| | | <NFormItem label="生效规则:"> |
| | | <div class="flex flex-col gap-16px w-full"> |
| | | <NRadioGroup v-model:value="strategy.effectRule"> |
| | | <NFormItem label="生效规则" class="mt-12px"> |
| | | <div class="flex flex-col pl-8px gap-8px w-full"> |
| | | <NRadioGroup v-model:value="strategy.effectRule" class="h-32px flex items-center"> |
| | | <NSpace> |
| | | <NRadio value="领取后生效" label="领取后生效" /> |
| | | <NRadio value="领取后指定日期生效" label="领取后指定日期生效" /> |
| | | <NRadio :value="1" label="领取后生效" /> |
| | | <NRadio :value="2" label="领取后指定日期生效" /> |
| | | </NSpace> |
| | | </NRadioGroup> |
| | | |
| | | <div v-if="strategy.effectRule === '领取后指定日期生效'" class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">生效日期</span> |
| | | <div v-if="strategy.effectRule === 2" class="flex items-center gap-16px"> |
| | | <span>生效日期</span> |
| | | <NDatePicker |
| | | v-model:value="strategy.effectDate" type="date" format="yyyy/MM/dd" clearable |
| | | :actions="null" close-on-select placeholder="请选择日期" style="width: 200px;" |
| | | :actions="null" close-on-select placeholder="请选择日期" style="width: 240px;" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </NFormItem> |
| | | |
| | | <!-- 失效规则 --> |
| | | <NFormItem label="失效规则:"> |
| | | <div class="flex flex-col gap-16px w-full"> |
| | | <NRadioGroup v-model:value="strategy.effectiveRules"> |
| | | <NFormItem label="失效规则" class="mt-12px"> |
| | | <div class="flex flex-col gap-8px w-full pl-8px"> |
| | | <NRadioGroup v-model:value="strategy.effectiveRules" class="h-32px flex items-center"> |
| | | <NSpace> |
| | | <NRadio :value="1" label="次日0点失效" /> |
| | | <NRadio :value="2" label="指定有效天数" /> |
| | |
| | | </NRadioGroup> |
| | | |
| | | <div v-if="strategy.effectiveRules === 2" class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">有效天数</span> |
| | | <span>有效天数</span> |
| | | <NInputNumber |
| | | v-model:value="strategy.effectiveDays" placeholder="请输入天数" :min="1" :show-button="false" |
| | | style="width: 200px;" |
| | | style="width: 240px;" |
| | | /> |
| | | </div> |
| | | <div v-if="strategy.effectiveRules === 3" class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">有效期至</span> |
| | | <span>有效期至</span> |
| | | <NDatePicker |
| | | v-model:value="strategy.endTime" type="date" format="yyyy/MM/dd" clearable |
| | | :actions="null" close-on-select placeholder="请选择日期" style="width: 200px;" |
| | | :actions="null" close-on-select placeholder="请选择日期" style="width: 240px;" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </NFormItem> |
| | | |
| | | <!-- 是否可叠加使用 --> |
| | | <NFormItem label="是否可叠加使用:"> |
| | | <NRadioGroup v-model:value="strategy.stackedUsage"> |
| | | <NFormItem label="是否可叠加使用" class="mt-8px"> |
| | | <NRadioGroup v-model:value="strategy.stackedUsage" class="h-32px flex items-center"> |
| | | <NSpace> |
| | | <NRadio :value="0" label="不可叠加" /> |
| | | <NRadio :value="1" label="可叠加" /> |
| | |
| | | </NFormItem> |
| | | |
| | | <!-- 使用限时 --> |
| | | <NFormItem label="使用限时:"> |
| | | <div class="flex flex-col gap-12px w-full"> |
| | | <span class="text-[#606266] text-14px">仅可在每天的以下时间段使用</span> |
| | | <NFormItem label="使用限时"> |
| | | <div class="flex flex-col w-full"> |
| | | <span class="text-[#171f26cc] text-13px h-32px line-height-32px">仅可在每天的以下时间段使用</span> |
| | | <div |
| | | v-for="(timeLimit, index) in strategy.usagePeriod" :key="index" |
| | | class="flex items-center gap-12px" |
| | | class="flex items-center gap-8px mt-8px" |
| | | > |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.startTime" format="HH:mm" value-format="HH:mm" |
| | | placeholder="请选择开始时间" style="width: 200px" |
| | | placeholder="请选择开始时间" style="width: 240px" |
| | | /> |
| | | <span class="text-[#909399]">至</span> |
| | | <span class="text-[#171f26cc]">至</span> |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.endTime" format="HH:mm" value-format="HH:mm" |
| | | placeholder="请选择结束时间" style="width: 200px" |
| | | placeholder="请选择结束时间" style="width: 240px" |
| | | /> |
| | | <div class="flex gap-8px ml-8px"> |
| | | <div |
| | | v-if="index === strategy.usagePeriod.length - 1 && strategy.usagePeriod.length < 10" |
| | | class="w-24px h-24px rounded-full border border-[#0068FF] text-[#0068FF] flex items-center justify-center cursor-pointer" |
| | | @click="handleAddTimeLimit(strategyIndex)" |
| | | > |
| | | <span class="text-16px leading-none">+</span> |
| | | </div> |
| | | <div |
| | | v-if="strategy.usagePeriod.length > 1" |
| | | class="w-24px h-24px rounded-full border border-[#C0C4CC] text-[#C0C4CC] flex items-center justify-center cursor-pointer" |
| | | @click="handleRemoveTimeLimit(strategyIndex, index)" |
| | | > |
| | | <span class="text-12px leading-none mt-[-2px]">一</span> |
| | | </div> |
| | | </div> |
| | | <img v-if="index > 0" :src="deleteIcon" alt="删除" style="width: 16px;height: 16px;cursor: pointer;" @click="handleRemoveTimeLimit(strategyIndex, index)"> |
| | | </div> |
| | | <NButton |
| | | type="primary" secondary style="border: 1px solid #7ABDFF;" class="w-509px mt-16px" |
| | | @click="handleAddTimeLimit(strategyIndex)" |
| | | > |
| | | <template #icon> |
| | | <icon-park-outline-plus style="font-size: 32px;" /> |
| | | </template> |
| | | 新增时间段 |
| | | </NButton> |
| | | </div> |
| | | </NFormItem> |
| | | |
| | | <!-- 数量和自动使用 --> |
| | | <div class="flex items-start gap-40px"> |
| | | <NFormItem label="每人限领数量:" class="flex-1"> |
| | | <div class="flex items-start gap-24px mt-16px"> |
| | | <NFormItem label="每人限领数量"> |
| | | <NInputNumber |
| | | v-model:value="strategy.limitNumber" placeholder="最小1张,最大10张" :min="1" :max="10" |
| | | :show-button="false" style="width: 100%" |
| | | :show-button="false" style="width: 240px" |
| | | /> |
| | | </NFormItem> |
| | | <NFormItem label="发放总量:" class="flex-1"> |
| | | <NFormItem label="发放总量"> |
| | | <NInputNumber |
| | | v-model:value="strategy.distributionsTotal" placeholder="若不填则不限数量" :min="1" |
| | | :show-button="false" style="width: 100%" |
| | | :show-button="false" style="width: 240px" |
| | | /> |
| | | </NFormItem> |
| | | </div> |
| | | |
| | | <NFormItem label="是否自动使用:"> |
| | | <NRadioGroup v-model:value="strategy.startUsing"> |
| | | <NFormItem label="是否自动使用" class="mt-8px"> |
| | | <NRadioGroup v-model:value="strategy.startUsing" class="h-32px flex items-center pl-8px"> |
| | | <NSpace> |
| | | <NRadio :value="0" label="不开启" /> |
| | | <NRadio :value="1" label="冒泡发单时自动使用" /> |
| | |
| | | </NForm> |
| | | </div> |
| | | |
| | | <div class="flex justify-center mt-24px pb-24px"> |
| | | <NButton type="primary" style="width: 400px" @click="handleAddStrategy"> |
| | | <div class="flex"> |
| | | <NButton type="primary" secondary style="width: 240px;border: 1px solid #7ABDFF;" @click="handleAddStrategy"> |
| | | 新增策略 |
| | | </NButton> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 发放用户 --> |
| | | <div v-show="activeTab === 3" class="flex flex-col gap-32px pb-24px"> |
| | | <div v-show="activeTab === 3" class="flex flex-col"> |
| | | <div |
| | | v-for="(group, groupIndex) in userGroupList" :key="groupIndex" |
| | | class="flex flex-col gap-24px border-b border-[#EBEEF5] last:border-b-0 pb-24px last:pb-0" |
| | | class="flex flex-col gap-24px border-b border-[#EBEEF5] last:border-b-0 pb-24px last:pb-0 mb-24px" |
| | | > |
| | | <div class="flex items-center gap-40px"> |
| | | <div class="flex items-center gap-24px"> |
| | | <div class="flex items-center gap-16px"> |
| | | <span class="text-[#606266]">用户类型</span> |
| | | <div class="flex items-center gap-8px"> |
| | | <div class="flex items-center gap-4px"> |
| | | <NRadioGroup v-model:value="group.userType"> |
| | | <NRadioButton :value="1" label="全部" /> |
| | | <NRadioButton :value="2" label="老用户" /> |
| | |
| | | <NRadioButton :value="5" label="指定用户" /> |
| | | </NRadioGroup> |
| | | <icon-park-outline-help |
| | | v-if="groupIndex === 0" color="#0256ff" class="cursor-pointer" |
| | | color="#0256ff" class="cursor-pointer" |
| | | @click="showUserTypeHelpModal = true" |
| | | /> |
| | | </div> |
| | |
| | | @update:value="(value) => syncUserGroupStrategy(groupIndex, value as number | null)" |
| | | /> |
| | | </div> |
| | | <img v-if="groupIndex > 0" :src="deleteIcon" alt="删除" style="width: 16px;height: 16px;cursor: pointer;margin-left: auto;" @click="handleRemoveUserGroup(groupIndex)"> |
| | | </div> |
| | | |
| | | <!-- 指定用户下的表格 --> |
| | | <div v-if="group.userType === 5" class="flex flex-col gap-16px w-full"> |
| | | <div> |
| | | <NButton type="primary" style="width: 100px;" @click="handleOpenUserModal(groupIndex)"> |
| | | <div v-if="group.userType === 5" class="flex flex-col gap-12px w-full"> |
| | | <div class="flex justify-end"> |
| | | <NButton type="primary" secondary style="width: 84px;border: 1px solid #7ABDFF;" @click="handleOpenUserModal(groupIndex)"> |
| | | 导入用户 |
| | | </NButton> |
| | | </div> |
| | | <div class="border border-[#EBEEF5] rounded-4px overflow-hidden"> |
| | | <div class="overflow-hidden"> |
| | | <NDataTable |
| | | :columns="createUserColumns(groupIndex)" :data="group.userList" :bordered="false" |
| | | size="small" style="height: 250px" flex-height |
| | | /> |
| | | :columns="createUserColumns(groupIndex)" |
| | | :data="group.userList" |
| | | :bordered="false" |
| | | flex-height |
| | | style="min-height: 263px" |
| | | :pagination="false" |
| | | > |
| | | <template #empty> |
| | | <div class="flex-center"> |
| | | <img src="/src/assets/element-img/no-data.png" style="width:123px;height:125px" @error="(e: any) => { e.target.src = 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/9bed493b-a6aa-4ef6-ac10-7f67f5c6adc5.png' }"> |
| | | </div> |
| | | </template> |
| | | </NDataTable> |
| | | </div> |
| | | <div class="flex justify-end mt-8px"> |
| | | <div v-if="group.pagination.total > 0" class="flex justify-end mt-8px"> |
| | | <Pagination |
| | | :count="group.pagination.total" :page="group.pagination.page" |
| | | :page-size="group.pagination.pageSize" |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="flex justify-center mt-24px"> |
| | | <div class="flex"> |
| | | <NButton |
| | | style="width: 400px; color: #0068FF; border-color: #7ABDFF; background-color: #E6F4FF;" |
| | | style="width: 240px; border: 1px solid #7ABDFF;" |
| | | secondary |
| | | type="primary" |
| | | @click="handleAddUserGroup" |
| | | > |
| | | 新增用户群 |
| | |
| | | </div> |
| | | |
| | | <!-- 通知方式 --> |
| | | <div v-show="activeTab === 4" class="flex flex-col gap-24px"> |
| | | <div class="flex items-center gap-24px"> |
| | | <span class="text-[#606266] shrink-0">通知方式:</span> |
| | | <div v-show="activeTab === 4" class="flex flex-col gap-12px"> |
| | | <div class="flex items-center gap-16px mb-8px"> |
| | | <span>通知方式</span> |
| | | <NCheckboxGroup v-model:value="notifyForm.noticeType"> |
| | | <NSpace item-style="display: flex; align-items: center;" :size="40"> |
| | | <NSpace item-style="display: flex; align-items: center;" :size="16"> |
| | | <NCheckbox :value="1" label="微信消息通知" /> |
| | | <NCheckbox :value="2" label="短信通知" /> |
| | | <NCheckbox :value="4" label="小程序弹窗通知" /> |
| | |
| | | |
| | | <div |
| | | v-if="notifyForm.noticeType.includes(1)" |
| | | class="bg-[#F8F9FA] rounded-8px p-24px flex flex-col gap-24px" |
| | | class="border border-[#EEE9E9] border-solid rounded-6px p-24px flex flex-col gap-16px" |
| | | > |
| | | <div class="text-[#171f26] font-bold text-14px"> |
| | | <div class=" font-bold text-14px"> |
| | | 微信消息配置 |
| | | </div> |
| | | |
| | | <div class="flex items-center gap-24px pl-16px"> |
| | | <span class="text-[#606266] shrink-0">触达时机:</span> |
| | | <div class="flex items-center gap-16px"> |
| | | <span>触达时机</span> |
| | | <NCheckboxGroup v-model:value="notifyForm.wechatTriggerTiming"> |
| | | <NSpace :size="40"> |
| | | <NSpace :size="16"> |
| | | <NCheckbox :value="1" label="券到账" /> |
| | | <NCheckbox :value="2" label="即将过期" /> |
| | | <NCheckbox :value="4" label="活动开始" /> |
| | |
| | | </NCheckboxGroup> |
| | | </div> |
| | | |
| | | <div class="flex items-center gap-12px pl-16px ml-[70px]"> |
| | | <span class="text-[#606266]">临近到期时间前</span> |
| | | <div class="flex items-center gap-8px ml-[70px]"> |
| | | <span>临近到期时间前</span> |
| | | <NInputNumber |
| | | v-model:value="notifyForm.wechatDaysBeforeExpiry" placeholder="请输入天数" :show-button="false" |
| | | style="width: 160px;" |
| | | style="width: 109px;" |
| | | /> |
| | | <span class="text-[#606266]">天,触达通知</span> |
| | | <span>天,触达通知</span> |
| | | |
| | | <span class="text-[#606266] ml-24px">临近券生效前</span> |
| | | <span class="text-[#606266] ml-16px">临近券生效前</span> |
| | | <NInputNumber |
| | | v-model:value="notifyForm.wechatMinutesBeforeEffective" placeholder="请输入分钟数" :show-button="false" |
| | | style="width: 160px;" |
| | | style="width: 109px;" |
| | | /> |
| | | <span class="text-[#606266]">分钟,触达通知</span> |
| | | <span>分钟,触达通知</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div |
| | | v-if="notifyForm.noticeType.includes(2)" |
| | | class="bg-[#F8F9FA] rounded-8px p-24px flex flex-col gap-24px" |
| | | class="border border-[#EEE9E9] border-solid rounded-6px p-24px flex flex-col gap-16px" |
| | | > |
| | | <div class="text-[#171f26] font-bold text-14px"> |
| | | <div class="font-bold text-14px"> |
| | | 短信通知配置 |
| | | </div> |
| | | |
| | | <div class="flex items-center gap-24px pl-16px"> |
| | | <span class="text-[#606266] shrink-0">触达时机:</span> |
| | | <div class="flex items-center gap-16px"> |
| | | <span>触达时机</span> |
| | | <NCheckboxGroup v-model:value="notifyForm.smsTriggerTiming"> |
| | | <NSpace :size="40"> |
| | | <NSpace :size="16"> |
| | | <NCheckbox :value="1" label="券到账" /> |
| | | <NCheckbox :value="2" label="即将过期" /> |
| | | <NCheckbox :value="4" label="活动开始" /> |
| | |
| | | </NCheckboxGroup> |
| | | </div> |
| | | |
| | | <div class="flex items-center gap-12px pl-16px ml-[70px]"> |
| | | <span class="text-[#606266]">临近到期时间前</span> |
| | | <div class="flex items-center gap-8px ml-[70px]"> |
| | | <span>临近到期时间前</span> |
| | | <NInputNumber |
| | | v-model:value="notifyForm.smsDaysBeforeExpiry" placeholder="请输入天数" :show-button="false" |
| | | style="width: 160px;" |
| | | style="width: 109px;" |
| | | /> |
| | | <span class="text-[#606266]">天,触达通知</span> |
| | | <span>天,触达通知</span> |
| | | |
| | | <span class="text-[#606266] ml-24px">临近券生效前</span> |
| | | <span class="text-[#606266] ml-16px">临近券生效前</span> |
| | | <NInputNumber |
| | | v-model:value="notifyForm.smsMinutesBeforeEffective" placeholder="请输入分钟数" :show-button="false" |
| | | style="width: 160px;" |
| | | style="width: 109px;" |
| | | /> |
| | | <span class="text-[#606266]">分钟,触达通知</span> |
| | | <span>分钟,触达通知</span> |
| | | </div> |
| | | |
| | | <div class="flex flex-col gap-12px pl-16px"> |
| | | <span class="text-[#606266] shrink-0">短信通知屏蔽时间:</span> |
| | | <div |
| | | v-for="(timeLimit, index) in notifyForm.blockTime" |
| | | :key="index" |
| | | class="flex items-center gap-12px" |
| | | > |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.startTime" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | placeholder="请选择开始时间" |
| | | style="width: 200px" |
| | | /> |
| | | <span class="text-[#909399]">至</span> |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.endTime" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | placeholder="请选择结束时间" |
| | | style="width: 200px" |
| | | /> |
| | | <div class="flex gap-8px ml-8px"> |
| | | <div |
| | | v-if="index === notifyForm.blockTime.length - 1 && notifyForm.blockTime.length < 10" |
| | | class="w-24px h-24px rounded-full border border-[#0068FF] text-[#0068FF] flex items-center justify-center cursor-pointer" |
| | | @click="handleAddBlockTime" |
| | | > |
| | | <span class="text-16px leading-none">+</span> |
| | | </div> |
| | | <div |
| | | v-if="notifyForm.blockTime.length > 1" |
| | | class="w-24px h-24px rounded-full border border-[#C0C4CC] text-[#C0C4CC] flex items-center justify-center cursor-pointer" |
| | | @click="handleRemoveBlockTime(index)" |
| | | > |
| | | <span class="text-12px leading-none mt-[-2px]">一</span> |
| | | <div class="flex gap-8px"> |
| | | <span>短信通知屏蔽时间</span> |
| | | <div class="flex flex-col gap-8px"> |
| | | <div |
| | | v-for="(timeLimit, index) in notifyForm.blockTime" |
| | | :key="index" |
| | | class="flex flex items-center gap-8px" |
| | | > |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.startTime" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | placeholder="请选择开始时间" |
| | | style="width: 240px" |
| | | /> |
| | | <span class="text-[#909399]">至</span> |
| | | <NTimePicker |
| | | v-model:formatted-value="timeLimit.endTime" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | placeholder="请选择结束时间" |
| | | style="width: 240px" |
| | | /> |
| | | <img v-if="index > 0" :src="deleteIcon" alt="删除" style="width: 16px;height: 16px;cursor: pointer;margin-left: auto;" @click="handleRemoveBlockTime(index)"> |
| | | <div class="flex gap-8px ml-8px"> |
| | | <div |
| | | v-if="index === notifyForm.blockTime.length - 1 && notifyForm.blockTime.length < 10" |
| | | class="w-24px h-24px rounded-full border border-[#0068FF] text-[#0068FF] flex items-center justify-center cursor-pointer" |
| | | @click="handleAddBlockTime" |
| | | > |
| | | <span class="text-16px leading-none">+</span> |
| | | </div> |
| | | <div |
| | | v-if="notifyForm.blockTime.length > 1" |
| | | class="w-24px h-24px rounded-full border border-[#C0C4CC] text-[#C0C4CC] flex items-center justify-center cursor-pointer" |
| | | @click="handleRemoveBlockTime(index)" |
| | | > |
| | | <span class="text-12px leading-none mt-[-2px]">一</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | |
| | | <div |
| | | v-if="notifyForm.noticeType.includes(4)" |
| | | class="bg-[#F8F9FA] rounded-8px p-24px flex flex-col gap-24px" |
| | | class="border border-[#EEE9E9] border-solid rounded-6px p-24px flex flex-col gap-16px" |
| | | > |
| | | <div class="text-[#171f26] font-bold text-14px"> |
| | | <div class=" font-bold text-14px"> |
| | | 小程序弹窗配置 |
| | | </div> |
| | | <div class="mini-popup-panel"> |
| | |
| | | |
| | | :deep(.n-form-item-label) { |
| | | padding-right: 8px !important; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.n-radio-button:first-child) { |
| | |
| | | width: 96px; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | :deep(.n-tabs-tab-pad) { |
| | | width: 24px !important; |
| | | } |
| | | |
| | | :deep(.n-tabs-pane-wrapper) { |
| | | height: 8px !important; |
| | | } |
| | | |
| | | :deep(.n-tabs-nav-scroll-content) { |
| | | border: none !important; |
| | | } |
| | | |
| | | :deep(.n-tabs-bar) { |
| | | height: 3px !important; |
| | | } |
| | | |
| | | :deep(.n-data-table-empty) { |
| | | border-bottom: 1px solid #EBEEF5; |
| | | box-sizing: border-box; |
| | | } |
| | | </style> |