商城:优惠劵的前端完善
							parent
							
								
									98477ef433
								
							
						
					
					
						commit
						815897ca8b
					
				|  | @ -1,12 +1,19 @@ | |||
| <template> | ||||
|   <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" /> | ||||
| 
 | ||||
|   <!-- 搜索工作栏 --> | ||||
|   <ContentWrap> | ||||
|     <!-- 搜索工作栏 --> | ||||
|     <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px"> | ||||
|     <el-form | ||||
|       ref="queryFormRef" | ||||
|       :inline="true" | ||||
|       :model="queryParams" | ||||
|       class="-mb-15px" | ||||
|       label-width="68px" | ||||
|     > | ||||
|       <el-form-item label="会员昵称" prop="nickname"> | ||||
|         <el-input | ||||
|           v-model="queryParams.nickname" | ||||
|           class="!w-240px" | ||||
|           placeholder="请输入会员昵称" | ||||
|           clearable | ||||
|           @keyup="handleQuery" | ||||
|  | @ -15,13 +22,12 @@ | |||
|       <el-form-item label="创建时间" prop="createTime"> | ||||
|         <el-date-picker | ||||
|           v-model="queryParams.createTime" | ||||
|           style="width: 240px" | ||||
|           type="datetimerange" | ||||
|           value-format="YYYY-MM-DD HH:mm:ss" | ||||
|           range-separator="-" | ||||
|           type="daterange" | ||||
|           start-placeholder="开始日期" | ||||
|           end-placeholder="结束日期" | ||||
|           :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]" | ||||
|           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" | ||||
|           class="!w-240px" | ||||
|         /> | ||||
|       </el-form-item> | ||||
|       <el-form-item> | ||||
|  | @ -31,11 +37,6 @@ | |||
|         <el-button @click="resetQuery"> <Icon icon="ep:refresh" class="mr-5px" />重置 </el-button> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
| 
 | ||||
|     <!-- 操作工具栏 --> | ||||
|     <!-- <el-row :gutter="10" class="mb8"> | ||||
|       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" /> | ||||
|     </el-row> --> | ||||
|   </ContentWrap> | ||||
| 
 | ||||
|   <ContentWrap> | ||||
|  | @ -86,23 +87,21 @@ | |||
|       <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|         <template #default="scope"> | ||||
|           <el-button | ||||
|             size="small" | ||||
|             type="primary" | ||||
|             link | ||||
|             @click="handleDelete(scope.row)" | ||||
|             v-hasPermi="['promotion:coupon:delete']" | ||||
|             ><Icon icon="ep:delete" :size="12" class="mr-1px" />回收</el-button | ||||
|             type="danger" | ||||
|             link | ||||
|             @click="handleDelete(scope.row.id)" | ||||
|           > | ||||
|             回收 | ||||
|           </el-button> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|     </el-table> | ||||
| 
 | ||||
|     <!-- 分页组件 --> | ||||
|     <pagination | ||||
|       v-show="total > 0" | ||||
|       :total="total" | ||||
|       v-model:page="queryParams.pageNo" | ||||
|     <!-- 分页 --> | ||||
|     <Pagination | ||||
|       v-model:limit="queryParams.pageSize" | ||||
|       v-model:page="queryParams.pageNo" | ||||
|       :total="total" | ||||
|       @pagination="getList" | ||||
|     /> | ||||
|   </ContentWrap> | ||||
|  | @ -112,17 +111,14 @@ | |||
| import { deleteCoupon, getCouponPage } from '@/api/mall/promotion/coupon' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { dateFormatter } from '@/utils/formatTime' | ||||
| import { FormInstance } from 'element-plus' | ||||
| 
 | ||||
| // 消息弹窗 | ||||
| const message = useMessage() | ||||
| defineOptions({ name: 'PromotionCoupon' }) | ||||
| 
 | ||||
| // 遮罩层 | ||||
| const loading = ref(true) | ||||
| // 总条数 | ||||
| const total = ref(0) | ||||
| // 优惠劵列表 | ||||
| const list = ref([]) | ||||
| const message = useMessage() // 消息弹窗 | ||||
| 
 | ||||
| const loading = ref(true) // 列表的加载中 | ||||
| const total = ref(0) // 列表的总页数 | ||||
| const list = ref([]) // 字典表格数据 | ||||
| // 查询参数 | ||||
| const queryParams = reactive({ | ||||
|   pageNo: 1, | ||||
|  | @ -130,9 +126,9 @@ const queryParams = reactive({ | |||
|   createTime: [], | ||||
|   status: undefined | ||||
| }) | ||||
| // Tab 筛选 | ||||
| const activeTab = ref('all') | ||||
| const queryFormRef = ref() // 搜索的表单 | ||||
| 
 | ||||
| const activeTab = ref('all') // Tab 筛选 | ||||
| const statusTabs = reactive([ | ||||
|   { | ||||
|     label: '全部', | ||||
|  | @ -140,8 +136,6 @@ const statusTabs = reactive([ | |||
|   } | ||||
| ]) | ||||
| 
 | ||||
| const queryFormRef = ref<FormInstance | null>(null) | ||||
| 
 | ||||
| /** 查询列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true | ||||
|  | @ -168,16 +162,17 @@ const resetQuery = () => { | |||
| } | ||||
| 
 | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row) => { | ||||
|   const id = row.id | ||||
| 
 | ||||
| const handleDelete = async (id: number) => { | ||||
|   try { | ||||
|     // 二次确认 | ||||
|     await message.confirm( | ||||
|       '回收将会收回会员领取的待使用的优惠券,已使用的将无法回收,确定要回收所选优惠券吗?' | ||||
|     ) | ||||
|     // 发起删除 | ||||
|     await deleteCoupon(id) | ||||
|     getList() | ||||
|     message.notifySuccess('回收成功') | ||||
|     // 重新加载列表 | ||||
|     await getList() | ||||
|   } catch {} | ||||
| } | ||||
| 
 | ||||
|  | @ -187,6 +182,7 @@ const onTabChange = (tabName) => { | |||
|   getList() | ||||
| } | ||||
| 
 | ||||
| /** 初始化 **/ | ||||
| onMounted(() => { | ||||
|   getList() | ||||
|   // 设置 statuses 过滤 | ||||
|  |  | |||
|  | @ -0,0 +1,348 @@ | |||
| <template> | ||||
|   <Dialog v-model="dialogVisible" :title="dialogTitle"> | ||||
|     <el-form | ||||
|       ref="formRef" | ||||
|       v-loading="formLoading" | ||||
|       :model="formData" | ||||
|       :rules="formRules" | ||||
|       label-width="140px" | ||||
|     > | ||||
|       <el-form-item label="优惠券名称" prop="name"> | ||||
|         <el-input v-model="formData.name" placeholder="请输入优惠券名称" /> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="优惠券类型" prop="discountType"> | ||||
|         <el-radio-group v-model="formData.discountType"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)" | ||||
|             :key="dict.value" | ||||
|             :label="dict.value" | ||||
|           > | ||||
|             {{ dict.label }} | ||||
|           </el-radio> | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.discountType === PromotionDiscountTypeEnum.PRICE.type" | ||||
|         label="优惠券面额" | ||||
|         prop="discountPrice" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="formData.discountPrice" | ||||
|           placeholder="请输入优惠金额,单位:元" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.discountType === PromotionDiscountTypeEnum.PERCENT.type" | ||||
|         label="优惠券折扣" | ||||
|         prop="discountPercent" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="formData.discountPercent" | ||||
|           placeholder="优惠券折扣不能小于 1 折,且不可大于 9.9 折" | ||||
|           style="width: 400px" | ||||
|           :precision="1" | ||||
|           :min="1" | ||||
|           :max="9.9" | ||||
|         /> | ||||
|         折 | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.discountType === PromotionDiscountTypeEnum.PERCENT.type" | ||||
|         label="最多优惠" | ||||
|         prop="discountLimitPrice" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="formData.discountLimitPrice" | ||||
|           placeholder="请输入最多优惠" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="满多少元可以使用" prop="usePrice"> | ||||
|         <el-input-number | ||||
|           v-model="formData.usePrice" | ||||
|           placeholder="无门槛请设为 0" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="领取方式" prop="takeType"> | ||||
|         <el-radio-group v-model="formData.takeType"> | ||||
|           <el-radio :key="1" :label="1">直接领取</el-radio> | ||||
|           <el-radio :key="2" :label="2">指定发放</el-radio> | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item v-if="formData.takeType === 1" label="发放数量" prop="totalCount"> | ||||
|         <el-input-number | ||||
|           v-model="formData.totalCount" | ||||
|           placeholder="发放数量,没有之后不能领取或发放,-1 为不限制" | ||||
|           style="width: 400px" | ||||
|           :precision="0" | ||||
|           :min="-1" | ||||
|         /> | ||||
|         张 | ||||
|       </el-form-item> | ||||
|       <el-form-item v-if="formData.takeType === 1" label="每人限领个数" prop="takeLimitCount"> | ||||
|         <el-input-number | ||||
|           v-model="formData.takeLimitCount" | ||||
|           placeholder="设置为 -1 时,可无限领取" | ||||
|           style="width: 400px" | ||||
|           :precision="0" | ||||
|           :min="-1" | ||||
|         /> | ||||
|         张 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="有效期类型" prop="validityType"> | ||||
|         <el-radio-group v-model="formData.validityType"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE)" | ||||
|             :key="dict.value" | ||||
|             :label="dict.value" | ||||
|           > | ||||
|             {{ dict.label }} | ||||
|           </el-radio> | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.validityType === CouponTemplateValidityTypeEnum.DATE.type" | ||||
|         label="固定日期" | ||||
|         prop="validTimes" | ||||
|       > | ||||
|         <el-date-picker | ||||
|           v-model="formData.validTimes" | ||||
|           style="width: 240px" | ||||
|           value-format="YYYY-MM-DD HH:mm:ss" | ||||
|           type="datetimerange" | ||||
|           :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]" | ||||
|         /> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.validityType === CouponTemplateValidityTypeEnum.TERM.type" | ||||
|         label="领取日期" | ||||
|         prop="fixedStartTerm" | ||||
|       > | ||||
|         第 | ||||
|         <el-input-number | ||||
|           v-model="formData.fixedStartTerm" | ||||
|           placeholder="0 为今天生效" | ||||
|           style="width: 165px" | ||||
|           :precision="0" | ||||
|           :min="0" | ||||
|         /> | ||||
|         至 | ||||
|         <el-input-number | ||||
|           v-model="formData.fixedEndTerm" | ||||
|           placeholder="请输入结束天数" | ||||
|           style="width: 165px" | ||||
|           :precision="0" | ||||
|           :min="0" | ||||
|         /> | ||||
|         天有效 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="活动商品" prop="productScope"> | ||||
|         <el-radio-group v-model="formData.productScope"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)" | ||||
|             :key="dict.value" | ||||
|             :label="dict.value" | ||||
|           > | ||||
|             {{ dict.label }} | ||||
|           </el-radio> | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="formData.productScope === PromotionProductScopeEnum.SPU.scope" | ||||
|         prop="productSpuIds" | ||||
|       > | ||||
|         <el-select | ||||
|           v-model="formData.productSpuIds" | ||||
|           placeholder="请选择活动商品" | ||||
|           clearable | ||||
|           multiple | ||||
|           filterable | ||||
|           style="width: 400px" | ||||
|         > | ||||
|           <el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id"> | ||||
|             <span style="float: left">{{ item.name }}</span> | ||||
|             <span style="float: right; font-size: 13px; color: #8492a6"> | ||||
|               ¥{{ (item.minPrice / 100.0).toFixed(2) }} | ||||
|             </span> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <template #footer> | ||||
|       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> | ||||
|       <el-button @click="dialogVisible = false">取 消</el-button> | ||||
|     </template> | ||||
|   </Dialog> | ||||
| </template> | ||||
| <script lang="ts" setup> | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import * as CouponTemplateApi from '@/api/mall/promotion/couponTemplate' | ||||
| import * as ProductSpuApi from '@/api/mall/product/spu' | ||||
| import { | ||||
|   CouponTemplateValidityTypeEnum, | ||||
|   PromotionDiscountTypeEnum, | ||||
|   PromotionProductScopeEnum | ||||
| } from '@/utils/constants' | ||||
| 
 | ||||
| defineOptions({ name: 'CouponTemplateForm' }) | ||||
| 
 | ||||
| const { t } = useI18n() // 国际化 | ||||
| const message = useMessage() // 消息弹窗 | ||||
| 
 | ||||
| const dialogVisible = ref(false) // 弹窗的是否展示 | ||||
| const dialogTitle = ref('') // 弹窗的标题 | ||||
| const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | ||||
| const formType = ref('') // 表单的类型:create - 新增;update - 修改 | ||||
| const formData = ref({ | ||||
|   id: undefined, | ||||
|   name: undefined, | ||||
|   discountType: PromotionDiscountTypeEnum.PRICE.type, | ||||
|   discountPrice: undefined, | ||||
|   discountPercent: undefined, | ||||
|   discountLimitPrice: undefined, | ||||
|   usePrice: undefined, | ||||
|   takeType: 1, | ||||
|   totalCount: undefined, | ||||
|   takeLimitCount: undefined, | ||||
|   validityType: CouponTemplateValidityTypeEnum.DATE.type, | ||||
|   validTimes: [], | ||||
|   validStartTime: undefined, | ||||
|   validEndTime: undefined, | ||||
|   fixedStartTerm: undefined, | ||||
|   fixedEndTerm: undefined, | ||||
|   productScope: PromotionProductScopeEnum.ALL.scope, | ||||
|   productSpuIds: [] | ||||
| }) | ||||
| const formRules = reactive({ | ||||
|   name: [{ required: true, message: '优惠券名称不能为空', trigger: 'blur' }], | ||||
|   discountType: [{ required: true, message: '优惠券类型不能为空', trigger: 'change' }], | ||||
|   discountPrice: [{ required: true, message: '优惠券面额不能为空', trigger: 'blur' }], | ||||
|   discountPercent: [{ required: true, message: '优惠券折扣不能为空', trigger: 'blur' }], | ||||
|   discountLimitPrice: [{ required: true, message: '最多优惠不能为空', trigger: 'blur' }], | ||||
|   usePrice: [{ required: true, message: '满多少元可以使用不能为空', trigger: 'blur' }], | ||||
|   takeType: [{ required: true, message: '领取方式不能为空', trigger: 'change' }], | ||||
|   totalCount: [{ required: true, message: '发放数量不能为空', trigger: 'blur' }], | ||||
|   takeLimitCount: [{ required: true, message: '每人限领个数不能为空', trigger: 'blur' }], | ||||
|   validityType: [{ required: true, message: '有效期类型不能为空', trigger: 'change' }], | ||||
|   validTimes: [{ required: true, message: '固定日期不能为空', trigger: 'change' }], | ||||
|   fixedStartTerm: [{ required: true, message: '开始领取天数不能为空', trigger: 'blur' }], | ||||
|   fixedEndTerm: [{ required: true, message: '开始领取天数不能为空', trigger: 'blur' }], | ||||
|   productScope: [{ required: true, message: '商品范围不能为空', trigger: 'blur' }], | ||||
|   productSpuIds: [{ required: true, message: '商品范围不能为空', trigger: 'blur' }] | ||||
| }) | ||||
| const formRef = ref() // 表单 Ref | ||||
| const productSpus = ref([]) // 商品列表 | ||||
| 
 | ||||
| /** 打开弹窗 */ | ||||
| const open = async (type: string, id?: number) => { | ||||
|   dialogVisible.value = true | ||||
|   dialogTitle.value = t('action.' + type) | ||||
|   formType.value = type | ||||
|   resetForm() | ||||
|   // 修改时,设置数据 | ||||
|   if (id) { | ||||
|     formLoading.value = true | ||||
|     try { | ||||
|       const data = await CouponTemplateApi.getCouponTemplate(id) | ||||
|       formData.value = { | ||||
|         ...data, | ||||
|         discountPrice: data.discountPrice !== undefined ? data.discountPrice / 100.0 : undefined, | ||||
|         discountPercent: | ||||
|           data.discountPercent !== undefined ? data.discountPercent / 10.0 : undefined, | ||||
|         discountLimitPrice: | ||||
|           data.discountLimitPrice !== undefined ? data.discountLimitPrice / 100.0 : undefined, | ||||
|         usePrice: data.usePrice !== undefined ? data.usePrice / 100.0 : undefined, | ||||
|         validTimes: [data.validStartTime, data.validEndTime] | ||||
|       } | ||||
|     } finally { | ||||
|       formLoading.value = false | ||||
|     } | ||||
|   } | ||||
|   // 获得商品列表 | ||||
|   productSpus.value = await ProductSpuApi.getSpuSimpleList() | ||||
| } | ||||
| defineExpose({ open }) // 提供 open 方法,用于打开弹窗 | ||||
| 
 | ||||
| /** 提交表单 */ | ||||
| const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 | ||||
| const submitForm = async () => { | ||||
|   // 校验表单 | ||||
|   if (!formRef) return | ||||
|   const valid = await formRef.value.validate() | ||||
|   if (!valid) return | ||||
|   // 提交请求 | ||||
|   formLoading.value = true | ||||
|   try { | ||||
|     const data = { | ||||
|       ...formData.value, | ||||
|       discountPrice: | ||||
|         formData.value.discountPrice !== undefined ? formData.value.discountPrice * 100 : undefined, | ||||
|       discountPercent: | ||||
|         formData.value.discountPercent !== undefined | ||||
|           ? formData.value.discountPercent * 10 | ||||
|           : undefined, | ||||
|       discountLimitPrice: | ||||
|         formData.value.discountLimitPrice !== undefined | ||||
|           ? formData.value.discountLimitPrice * 100 | ||||
|           : undefined, | ||||
|       usePrice: formData.value.usePrice !== undefined ? formData.value.usePrice * 100 : undefined, | ||||
|       validStartTime: | ||||
|         formData.value.validTimes && formData.value.validTimes.length === 2 | ||||
|           ? formData.value.validTimes[0] | ||||
|           : undefined, | ||||
|       validEndTime: | ||||
|         formData.value.validTimes && formData.value.validTimes.length === 2 | ||||
|           ? formData.value.validTimes[1] | ||||
|           : undefined | ||||
|     } as CouponTemplateApi.CouponTemplateVO | ||||
|     if (formType.value === 'create') { | ||||
|       await CouponTemplateApi.createCouponTemplate(data) | ||||
|       message.success(t('common.createSuccess')) | ||||
|     } else { | ||||
|       await CouponTemplateApi.updateCouponTemplate(data) | ||||
|       message.success(t('common.updateSuccess')) | ||||
|     } | ||||
|     dialogVisible.value = false | ||||
|     // 发送操作成功的事件 | ||||
|     emit('success') | ||||
|   } finally { | ||||
|     formLoading.value = false | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 重置表单 */ | ||||
| const resetForm = () => { | ||||
|   formData.value = { | ||||
|     id: undefined, | ||||
|     name: undefined, | ||||
|     discountType: PromotionDiscountTypeEnum.PRICE.type, | ||||
|     discountPrice: undefined, | ||||
|     discountPercent: undefined, | ||||
|     discountLimitPrice: undefined, | ||||
|     usePrice: undefined, | ||||
|     takeType: 1, | ||||
|     totalCount: undefined, | ||||
|     takeLimitCount: undefined, | ||||
|     validityType: CouponTemplateValidityTypeEnum.DATE.type, | ||||
|     validTimes: [], | ||||
|     validStartTime: undefined, | ||||
|     validEndTime: undefined, | ||||
|     fixedStartTerm: undefined, | ||||
|     fixedEndTerm: undefined, | ||||
|     productScope: PromotionProductScopeEnum.ALL.scope, | ||||
|     productSpuIds: [] | ||||
|   } | ||||
|   formRef.value?.resetFields() | ||||
| } | ||||
| </script> | ||||
|  | @ -65,31 +65,24 @@ | |||
|           <Icon icon="ep:search" class="mr-5px" /> 搜索 | ||||
|         </el-button> | ||||
|         <el-button @click="resetQuery"> <Icon icon="ep:refresh" class="mr-5px" />重置 </el-button> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
| 
 | ||||
|     <!-- 操作工具栏 --> | ||||
|     <el-row :gutter="10" class="mb8"> | ||||
|       <el-col :span="1.5"> | ||||
|         <el-button | ||||
|           type="primary" | ||||
|           plain | ||||
|           @click="handleAdd" | ||||
|           v-hasPermi="['promotion:coupon-template:create']" | ||||
|           plain | ||||
|           type="primary" | ||||
|           @click="openForm('create')" | ||||
|         > | ||||
|           <Icon icon="ep:plus" class="mr-5px" />新增 | ||||
|           <Icon class="mr-5px" icon="ep:plus" /> 新增 | ||||
|         </el-button> | ||||
|         <el-button | ||||
|           type="info" | ||||
|           plain | ||||
|           type="success" | ||||
|           @click="$router.push('/promotion/coupon')" | ||||
|           v-hasPermi="['promotion:coupon:query']" | ||||
|         > | ||||
|           <Icon icon="ep:operation" class="mr-5px" />会员优惠劵 | ||||
|         </el-button> | ||||
|       </el-col> | ||||
|       <!-- <right-toolbar v-model:showSearch="showSearch" @query-table="getList" /> --> | ||||
|     </el-row> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|   </ContentWrap> | ||||
| 
 | ||||
|   <!-- 列表 --> | ||||
|  | @ -124,7 +117,7 @@ | |||
|         label="有效期限" | ||||
|         align="center" | ||||
|         prop="validityType" | ||||
|         width="180" | ||||
|         width="190" | ||||
|         :formatter="validityTypeFormat" | ||||
|       /> | ||||
|       <el-table-column label="状态" align="center" prop="status"> | ||||
|  | @ -147,255 +140,56 @@ | |||
|       <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> | ||||
|         <template #default="scope"> | ||||
|           <el-button | ||||
|             size="small" | ||||
|             type="primary" | ||||
|             link | ||||
|             @click="handleUpdate(scope.row)" | ||||
|             v-hasPermi="['promotion:coupon-template:update']" | ||||
|             link | ||||
|             type="primary" | ||||
|             @click="openForm('update', scope.row.id)" | ||||
|           > | ||||
|             <Icon icon="ep:edit" :size="12" class="mr-1px" /> | ||||
|             修改 | ||||
|           </el-button> | ||||
|           <el-button | ||||
|             size="small" | ||||
|             type="primary" | ||||
|             link | ||||
|             @click="handleDelete(scope.row)" | ||||
|             v-hasPermi="['promotion:coupon-template:delete']" | ||||
|             link | ||||
|             type="danger" | ||||
|             @click="handleDelete(scope.row.id)" | ||||
|           > | ||||
|             <Icon icon="ep:delete" :size="12" class="mr-1px" /> | ||||
|             删除 | ||||
|           </el-button> | ||||
|         </template> | ||||
|       </el-table-column> | ||||
|     </el-table> | ||||
|     <!-- 分页 --> | ||||
|     <Pagination | ||||
|       v-model:limit="queryParams.pageSize" | ||||
|       v-model:page="queryParams.pageNo" | ||||
|       :total="total" | ||||
|       @pagination="getList" | ||||
|     /> | ||||
|   </ContentWrap> | ||||
| 
 | ||||
|   <!-- 分页组件 --> | ||||
|   <pagination | ||||
|     v-show="total > 0" | ||||
|     :total="total" | ||||
|     v-model:page="queryParams.pageNo" | ||||
|     v-model:limit="queryParams.pageSize" | ||||
|     @pagination="getList" | ||||
|   /> | ||||
| 
 | ||||
|   <!-- 对话框(添加 / 修改) --> | ||||
|   <el-dialog :title="title" v-model="open" width="600px" append-to-body> | ||||
|     <el-form ref="formRef" :model="form" :rules="rules" label-width="140px"> | ||||
|       <el-form-item label="优惠券名称" prop="name"> | ||||
|         <el-input v-model="form.name" placeholder="请输入优惠券名称" /> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="优惠券类型" prop="discountType"> | ||||
|         <el-radio-group v-model="form.discountType"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)" | ||||
|             :key="dict.value" | ||||
|             :label="parseInt(dict.value)" | ||||
|             >{{ dict.label }}</el-radio | ||||
|           > | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.discountType === PromotionDiscountTypeEnum.PRICE.type" | ||||
|         label="优惠券面额" | ||||
|         prop="discountPrice" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="form.discountPrice" | ||||
|           placeholder="请输入优惠金额,单位:元" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" | ||||
|         label="优惠券折扣" | ||||
|         prop="discountPercent" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="form.discountPercent" | ||||
|           placeholder="优惠券折扣不能小于 1 折,且不可大于 9.9 折" | ||||
|           style="width: 400px" | ||||
|           :precision="1" | ||||
|           :min="1" | ||||
|           :max="9.9" | ||||
|         /> | ||||
|         折 | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" | ||||
|         label="最多优惠" | ||||
|         prop="discountLimitPrice" | ||||
|       > | ||||
|         <el-input-number | ||||
|           v-model="form.discountLimitPrice" | ||||
|           placeholder="请输入最多优惠" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="满多少元可以使用" prop="usePrice"> | ||||
|         <el-input-number | ||||
|           v-model="form.usePrice" | ||||
|           placeholder="无门槛请设为 0" | ||||
|           style="width: 400px" | ||||
|           :precision="2" | ||||
|           :min="0" | ||||
|         /> | ||||
|         元 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="领取方式" prop="takeType"> | ||||
|         <el-radio-group v-model="form.takeType"> | ||||
|           <el-radio :key="1" :label="1">直接领取</el-radio> | ||||
|           <el-radio :key="2" :label="2">指定发放</el-radio> | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item v-if="form.takeType === 1" label="发放数量" prop="totalCount"> | ||||
|         <el-input-number | ||||
|           v-model="form.totalCount" | ||||
|           placeholder="发放数量,没有之后不能领取或发放,-1 为不限制" | ||||
|           style="width: 400px" | ||||
|           :precision="0" | ||||
|           :min="-1" | ||||
|         /> | ||||
|         张 | ||||
|       </el-form-item> | ||||
|       <el-form-item v-if="form.takeType === 1" label="每人限领个数" prop="takeLimitCount"> | ||||
|         <el-input-number | ||||
|           v-model="form.takeLimitCount" | ||||
|           placeholder="设置为 -1 时,可无限领取" | ||||
|           style="width: 400px" | ||||
|           :precision="0" | ||||
|           :min="-1" | ||||
|         /> | ||||
|         张 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="有效期类型" prop="validityType"> | ||||
|         <el-radio-group v-model="form.validityType"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE)" | ||||
|             :key="dict.value" | ||||
|             :label="parseInt(dict.value)" | ||||
|             >{{ dict.label }}</el-radio | ||||
|           > | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.validityType === CouponTemplateValidityTypeEnum.DATE.type" | ||||
|         label="固定日期" | ||||
|         prop="validTimes" | ||||
|       > | ||||
|         <el-date-picker | ||||
|           v-model="form.validTimes" | ||||
|           style="width: 240px" | ||||
|           value-format="YYYY-MM-DD HH:mm:ss" | ||||
|           type="datetimerange" | ||||
|           :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]" | ||||
|         /> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.validityType === CouponTemplateValidityTypeEnum.TERM.type" | ||||
|         label="领取日期" | ||||
|         prop="fixedStartTerm" | ||||
|       > | ||||
|         第 | ||||
|         <el-input-number | ||||
|           v-model="form.fixedStartTerm" | ||||
|           placeholder="0 为今天生效" | ||||
|           style="width: 165px" | ||||
|           :precision="0" | ||||
|           :min="0" | ||||
|         /> | ||||
|         至 | ||||
|         <el-input-number | ||||
|           v-model="form.fixedEndTerm" | ||||
|           placeholder="请输入结束天数" | ||||
|           style="width: 165px" | ||||
|           :precision="0" | ||||
|           :min="0" | ||||
|         /> | ||||
|         天有效 | ||||
|       </el-form-item> | ||||
|       <el-form-item label="活动商品" prop="productScope"> | ||||
|         <el-radio-group v-model="form.productScope"> | ||||
|           <el-radio | ||||
|             v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)" | ||||
|             :key="dict.value" | ||||
|             :label="parseInt(dict.value)" | ||||
|             >{{ dict.label }}</el-radio | ||||
|           > | ||||
|         </el-radio-group> | ||||
|       </el-form-item> | ||||
|       <el-form-item | ||||
|         v-if="form.productScope === PromotionProductScopeEnum.SPU.scope" | ||||
|         prop="productSpuIds" | ||||
|       > | ||||
|         <el-select | ||||
|           v-model="form.productSpuIds" | ||||
|           placeholder="请选择活动商品" | ||||
|           clearable | ||||
|           size="small" | ||||
|           multiple | ||||
|           filterable | ||||
|           style="width: 400px" | ||||
|         > | ||||
|           <el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id"> | ||||
|             <span style="float: left">{{ item.name }}</span> | ||||
|             <span style="float: right; font-size: 13px; color: #8492a6" | ||||
|               >¥{{ (item.minPrice / 100.0).toFixed(2) }}</span | ||||
|             > | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <template #footer> | ||||
|       <div class="dialog-footer"> | ||||
|         <el-button type="primary" @click="submitForm">确 定</el-button> | ||||
|         <el-button @click="cancel">取 消</el-button> | ||||
|       </div> | ||||
|     </template> | ||||
|   </el-dialog> | ||||
|   <!-- 表单弹窗:添加/修改 --> | ||||
|   <CouponTemplateForm ref="formRef" @success="getList" /> | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts" name="PromotionCouponTemplate"> | ||||
| import { | ||||
|   createCouponTemplate, | ||||
|   updateCouponTemplate, | ||||
|   deleteCouponTemplate, | ||||
|   getCouponTemplate, | ||||
|   getCouponTemplatePage, | ||||
|   updateCouponTemplateStatus | ||||
| } from '@/api/mall/promotion/couponTemplate' | ||||
| <script lang="ts" setup> | ||||
| import * as CouponTemplateApi from '@/api/mall/promotion/couponTemplate' | ||||
| import { | ||||
|   CommonStatusEnum, | ||||
|   CouponTemplateValidityTypeEnum, | ||||
|   PromotionDiscountTypeEnum, | ||||
|   PromotionProductScopeEnum | ||||
|   PromotionDiscountTypeEnum | ||||
| } from '@/utils/constants' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { getSpuSimpleList } from '@/api/mall/product/spu' | ||||
| import { dateFormatter, formatDate } from '@/utils/formatTime' | ||||
| import { FormInstance } from 'element-plus' | ||||
| import CouponTemplateForm from './CouponTemplateForm.vue' | ||||
| 
 | ||||
| // 消息弹窗 | ||||
| const message = useMessage() | ||||
| defineOptions({ name: 'PromotionCouponTemplate' }) | ||||
| 
 | ||||
| // 遮罩层 | ||||
| const loading = ref(true) | ||||
| // 总条数 | ||||
| const total = ref(0) | ||||
| // 优惠劵列表 | ||||
| const list = ref([]) | ||||
| // 弹出层标题 | ||||
| const title = ref('') | ||||
| // 是否显示弹出层 | ||||
| const open = ref(false) | ||||
| // 查询参数 | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const { t } = useI18n() // 国际化 | ||||
| 
 | ||||
| const loading = ref(true) // 列表的加载中 | ||||
| const total = ref(0) // 列表的总页数 | ||||
| const list = ref([]) // 字典表格数据 | ||||
| const queryParams = reactive({ | ||||
|   pageNo: 1, | ||||
|   pageSize: 10, | ||||
|  | @ -404,81 +198,21 @@ const queryParams = reactive({ | |||
|   type: null, | ||||
|   createTime: [] | ||||
| }) | ||||
| // 表单参数 | ||||
| const form = ref<any>({}) | ||||
| // 表单校验 | ||||
| const rules = { | ||||
|   name: [{ required: true, message: '优惠券名称不能为空', trigger: 'blur' }], | ||||
|   discountType: [{ required: true, message: '优惠券类型不能为空', trigger: 'change' }], | ||||
|   discountPrice: [{ required: true, message: '优惠券面额不能为空', trigger: 'blur' }], | ||||
|   discountPercent: [{ required: true, message: '优惠券折扣不能为空', trigger: 'blur' }], | ||||
|   discountLimitPrice: [{ required: true, message: '最多优惠不能为空', trigger: 'blur' }], | ||||
|   usePrice: [{ required: true, message: '满多少元可以使用不能为空', trigger: 'blur' }], | ||||
|   takeType: [{ required: true, message: '领取方式不能为空', trigger: 'change' }], | ||||
|   totalCount: [{ required: true, message: '发放数量不能为空', trigger: 'blur' }], | ||||
|   takeLimitCount: [{ required: true, message: '每人限领个数不能为空', trigger: 'blur' }], | ||||
|   validityType: [{ required: true, message: '有效期类型不能为空', trigger: 'change' }], | ||||
|   validTimes: [{ required: true, message: '固定日期不能为空', trigger: 'change' }], | ||||
|   fixedStartTerm: [{ required: true, message: '开始领取天数不能为空', trigger: 'blur' }], | ||||
|   fixedEndTerm: [{ required: true, message: '开始领取天数不能为空', trigger: 'blur' }], | ||||
|   productScope: [{ required: true, message: '商品范围不能为空', trigger: 'blur' }], | ||||
|   productSpuIds: [{ required: true, message: '商品范围不能为空', trigger: 'blur' }] | ||||
| } | ||||
| // 商品列表 | ||||
| const productSpus = ref([]) | ||||
| const queryFormRef = ref<FormInstance | null>(null) | ||||
| const formRef = ref<FormInstance | null>(null) | ||||
| 
 | ||||
| onMounted(() => { | ||||
|   getList() | ||||
| }) | ||||
| const queryFormRef = ref() // 搜索的表单 | ||||
| 
 | ||||
| /** 查询列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true | ||||
|   try { | ||||
|     // 执行查询 | ||||
|     const data = await getCouponTemplatePage(queryParams) | ||||
|     const data = await CouponTemplateApi.getCouponTemplatePage(queryParams) | ||||
|     list.value = data.list | ||||
|     total.value = data.total | ||||
|     // 查询商品列表 | ||||
|     productSpus.value = await getSpuSimpleList() | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 取消按钮 */ | ||||
| const cancel = () => { | ||||
|   open.value = false | ||||
|   reset() | ||||
| } | ||||
| 
 | ||||
| /** 表单重置 */ | ||||
| const reset = () => { | ||||
|   form.value = { | ||||
|     id: undefined, | ||||
|     name: undefined, | ||||
|     discountType: PromotionDiscountTypeEnum.PRICE.type, | ||||
|     discountPrice: undefined, | ||||
|     discountPercent: undefined, | ||||
|     discountLimitPrice: undefined, | ||||
|     usePrice: undefined, | ||||
|     takeType: 1, | ||||
|     totalCount: undefined, | ||||
|     takeLimitCount: undefined, | ||||
|     validityType: CouponTemplateValidityTypeEnum.DATE.type, | ||||
|     validTimes: [], | ||||
|     validStartTime: undefined, | ||||
|     validEndTime: undefined, | ||||
|     fixedStartTerm: undefined, | ||||
|     fixedEndTerm: undefined, | ||||
|     productScope: PromotionProductScopeEnum.ALL.scope, | ||||
|     productSpuIds: [] | ||||
|   } | ||||
|   formRef.value?.resetFields() | ||||
| } | ||||
| 
 | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.pageNo = 1 | ||||
|  | @ -491,78 +225,10 @@ const resetQuery = () => { | |||
|   handleQuery() | ||||
| } | ||||
| 
 | ||||
| /** 新增按钮操作 */ | ||||
| const handleAdd = () => { | ||||
|   reset() | ||||
|   open.value = true | ||||
|   title.value = '添加优惠劵' | ||||
| } | ||||
| 
 | ||||
| /** 修改按钮操作 */ | ||||
| const handleUpdate = async (row: any) => { | ||||
|   reset() | ||||
|   const id = row.id | ||||
|   try { | ||||
|     const data = await getCouponTemplate(id) | ||||
|     form.value = { | ||||
|       ...data, | ||||
|       discountPrice: data.discountPrice !== undefined ? data.discountPrice / 100.0 : undefined, | ||||
|       discountPercent: data.discountPercent !== undefined ? data.discountPercent / 10.0 : undefined, | ||||
|       discountLimitPrice: | ||||
|         data.discountLimitPrice !== undefined ? data.discountLimitPrice / 100.0 : undefined, | ||||
|       usePrice: data.usePrice !== undefined ? data.usePrice / 100.0 : undefined, | ||||
|       validTimes: [data.validStartTime, data.validEndTime] | ||||
|     } | ||||
|     open.value = true | ||||
|     title.value = '修改优惠劵' | ||||
|   } catch {} | ||||
| } | ||||
| 
 | ||||
| /** 提交按钮 */ | ||||
| const submitForm = async () => { | ||||
|   const valid = await formRef.value?.validate() | ||||
|   if (!valid) { | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   // 金额相关字段的缩放 | ||||
|   let data = { | ||||
|     ...form.value, | ||||
|     discountPrice: | ||||
|       form.value.discountPrice !== undefined ? form.value.discountPrice * 100 : undefined, | ||||
|     discountPercent: | ||||
|       form.value.discountPercent !== undefined ? form.value.discountPercent * 10 : undefined, | ||||
|     discountLimitPrice: | ||||
|       form.value.discountLimitPrice !== undefined ? form.value.discountLimitPrice * 100 : undefined, | ||||
|     usePrice: form.value.usePrice !== undefined ? form.value.usePrice * 100 : undefined, | ||||
|     validStartTime: | ||||
|       form.value.validTimes && form.value.validTimes.length === 2 | ||||
|         ? form.value.validTimes[0] | ||||
|         : undefined, | ||||
|     validEndTime: | ||||
|       form.value.validTimes && form.value.validTimes.length === 2 | ||||
|         ? form.value.validTimes[1] | ||||
|         : undefined | ||||
|   } | ||||
| 
 | ||||
|   // 修改的提交 | ||||
|   if (form.value.id != null) { | ||||
|     try { | ||||
|       await updateCouponTemplate(data) | ||||
|       message.success('修改成功') | ||||
|       open.value = false | ||||
|       getList() | ||||
|     } catch {} | ||||
| 
 | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   try { | ||||
|     await createCouponTemplate(data) | ||||
|     message.success('新增成功') | ||||
|     open.value = false | ||||
|     getList() | ||||
|   } catch {} | ||||
| /** 添加/修改操作 */ | ||||
| const formRef = ref() | ||||
| const openForm = (type: string, id?: number) => { | ||||
|   formRef.value.open(type, id) | ||||
| } | ||||
| 
 | ||||
| /** 优惠劵模板状态修改 */ | ||||
|  | @ -572,7 +238,7 @@ const handleStatusChange = async (row: any) => { | |||
| 
 | ||||
|   try { | ||||
|     await message.confirm('确认要"' + text + '""' + row.name + '"优惠劵吗?') | ||||
|     await updateCouponTemplateStatus(row.id, row.status) | ||||
|     await CouponTemplateApi.updateCouponTemplateStatus(row.id, row.status) | ||||
|     message.success(text + '成功') | ||||
|   } catch { | ||||
|     // 异常时,需要将 row.status 状态重置回之前的 | ||||
|  | @ -582,11 +248,15 @@ const handleStatusChange = async (row: any) => { | |||
| } | ||||
| 
 | ||||
| /** 删除按钮操作 */ | ||||
| const handleDelete = async (row: any) => { | ||||
|   const id = row.id | ||||
| const handleDelete = async (id: number) => { | ||||
|   try { | ||||
|     // 删除的二次确认 | ||||
|     await message.confirm('是否确认删除优惠劵编号为"' + id + '"的数据项?') | ||||
|     await deleteCouponTemplate(id) | ||||
|     // 发起删除 | ||||
|     await CouponTemplateApi.deleteCouponTemplate(id) | ||||
|     message.success(t('common.delSuccess')) | ||||
|     // 刷新列表 | ||||
|     await getList() | ||||
|   } catch {} | ||||
| } | ||||
| 
 | ||||
|  | @ -619,4 +289,9 @@ const validityTypeFormat = (row: any) => { | |||
|   } | ||||
|   return '未知【' + row.validityType + '】' | ||||
| } | ||||
| 
 | ||||
| /** 初始化 **/ | ||||
| onMounted(() => { | ||||
|   getList() | ||||
| }) | ||||
| </script> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 YunaiV
						YunaiV