RewardForm.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <template>
  2. <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%">
  3. <el-form
  4. ref="formRef"
  5. v-loading="formLoading"
  6. :model="formData"
  7. :rules="formRules"
  8. label-width="80px"
  9. >
  10. <el-form-item label="活动名称" prop="name">
  11. <el-input v-model="formData.name" placeholder="请输入活动名称" />
  12. </el-form-item>
  13. <el-form-item label="活动时间" prop="startAndEndTime">
  14. <el-date-picker
  15. v-model="formData.startAndEndTime"
  16. :end-placeholder="t('common.endTimeText')"
  17. :start-placeholder="t('common.startTimeText')"
  18. range-separator="-"
  19. type="datetimerange"
  20. />
  21. </el-form-item>
  22. <el-form-item label="条件类型" prop="conditionType">
  23. <el-radio-group v-model="formData.conditionType">
  24. <el-radio
  25. v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_CONDITION_TYPE)"
  26. :key="dict.value"
  27. :label="dict.value"
  28. >
  29. {{ dict.label }}
  30. </el-radio>
  31. </el-radio-group>
  32. </el-form-item>
  33. <el-form-item label="优惠设置">
  34. <RewardRule v-model="formData" />
  35. </el-form-item>
  36. <el-form-item label="活动范围" prop="productScope">
  37. <el-radio-group v-model="formData.productScope">
  38. <el-radio
  39. v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)"
  40. :key="dict.value"
  41. :label="dict.value"
  42. >
  43. {{ dict.label }}
  44. </el-radio>
  45. </el-radio-group>
  46. </el-form-item>
  47. <el-form-item
  48. v-if="formData.productScope === PromotionProductScopeEnum.SPU.scope"
  49. prop="productSpuIds"
  50. >
  51. <SpuShowcase v-model="formData.productSpuIds" />
  52. </el-form-item>
  53. <el-form-item
  54. v-if="formData.productScope === PromotionProductScopeEnum.CATEGORY.scope"
  55. label="分类"
  56. prop="productCategoryIds"
  57. >
  58. <ProductCategorySelect v-model="formData.productCategoryIds" />
  59. </el-form-item>
  60. <el-form-item label="备注" prop="remark">
  61. <el-input v-model="formData.remark" placeholder="请输入备注" />
  62. </el-form-item>
  63. </el-form>
  64. <template #footer>
  65. <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
  66. <el-button @click="dialogVisible = false">取 消</el-button>
  67. </template>
  68. </Dialog>
  69. </template>
  70. <script lang="ts" setup>
  71. import RewardRule from './components/RewardRule.vue'
  72. import SpuShowcase from '@/views/mall/product/spu/components/SpuShowcase.vue'
  73. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  74. import * as RewardActivityApi from '@/api/mall/promotion/reward/rewardActivity'
  75. import { PromotionConditionTypeEnum, PromotionProductScopeEnum } from '@/utils/constants'
  76. import ProductCategorySelect from '@/views/mall/product/category/components/ProductCategorySelect.vue'
  77. defineOptions({ name: 'ProductBrandForm' })
  78. const { t } = useI18n() // 国际化
  79. const message = useMessage() // 消息弹窗
  80. const dialogVisible = ref(false) // 弹窗的是否展示
  81. const dialogTitle = ref('') // 弹窗的标题
  82. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  83. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  84. const formData = ref<RewardActivityApi.RewardActivityVO>({
  85. conditionType: PromotionConditionTypeEnum.PRICE.type,
  86. productScope: PromotionProductScopeEnum.ALL.scope,
  87. rules: []
  88. } as RewardActivityApi.RewardActivityVO)
  89. const formRules = reactive({
  90. name: [{ required: true, message: '活动名称不能为空', trigger: 'blur' }],
  91. startAndEndTime: [{ required: true, message: '活动时间不能为空', trigger: 'blur' }],
  92. conditionType: [{ required: true, message: '条件类型不能为空', trigger: 'change' }],
  93. productScope: [{ required: true, message: '商品范围不能为空', trigger: 'blur' }],
  94. productSpuIds: [{ required: true, message: '商品不能为空', trigger: 'blur' }],
  95. productCategoryIds: [{ required: true, message: '商品分类不能为空', trigger: 'blur' }]
  96. })
  97. const formRef = ref([]) // 表单 Ref
  98. /** 打开弹窗 */
  99. const open = async (type: string, id?: number) => {
  100. dialogVisible.value = true
  101. dialogTitle.value = t('action.' + type)
  102. formType.value = type
  103. resetForm()
  104. // 修改时,设置数据
  105. if (id) {
  106. formLoading.value = true
  107. try {
  108. const data = await RewardActivityApi.getReward(id)
  109. data.startAndEndTime = [data.startTime, data.endTime]
  110. formData.value = data
  111. // 获得商品范围
  112. await getProductScope()
  113. } finally {
  114. formLoading.value = false
  115. }
  116. }
  117. }
  118. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  119. /** 提交表单 */
  120. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  121. const submitForm = async () => {
  122. // 校验表单
  123. if (!formRef) return
  124. // TODO puhui999: 规则校验
  125. // const valid = await formRef.value.validate()
  126. // if (!valid) return
  127. // TODO puhui999: 处理下数据兼容接口
  128. // 提交请求
  129. formLoading.value = true
  130. try {
  131. const data = formData.value
  132. // 设置商品范围
  133. setProductScopeValues(data)
  134. if (formType.value === 'create') {
  135. await RewardActivityApi.createRewardActivity(data)
  136. message.success(t('common.createSuccess'))
  137. } else {
  138. await RewardActivityApi.updateRewardActivity(data)
  139. message.success(t('common.updateSuccess'))
  140. }
  141. dialogVisible.value = false
  142. // 发送操作成功的事件
  143. emit('success')
  144. } finally {
  145. formLoading.value = false
  146. }
  147. }
  148. /** 重置表单 */
  149. const resetForm = () => {
  150. formData.value = {
  151. conditionType: PromotionConditionTypeEnum.PRICE.type,
  152. productScope: PromotionProductScopeEnum.ALL.scope,
  153. rules: []
  154. } as RewardActivityApi.RewardActivityVO
  155. }
  156. /** 获得商品范围 */
  157. const getProductScope = async () => {
  158. switch (formData.value.productScope) {
  159. case PromotionProductScopeEnum.SPU.scope:
  160. // 设置商品编号
  161. formData.value.productSpuIds = formData.value.productScopeValues
  162. break
  163. case PromotionProductScopeEnum.CATEGORY.scope:
  164. await nextTick(() => {
  165. let productCategoryIds = formData.value.productScopeValues as any
  166. if (Array.isArray(productCategoryIds) && productCategoryIds.length > 0) {
  167. // 单选时使用数组不能反显
  168. productCategoryIds = productCategoryIds[0]
  169. }
  170. // 设置品类编号
  171. formData.value.productCategoryIds = productCategoryIds
  172. })
  173. break
  174. default:
  175. break
  176. }
  177. }
  178. /** 设置商品范围 */
  179. function setProductScopeValues(data: any) {
  180. switch (formData.value.productScope) {
  181. case PromotionProductScopeEnum.SPU.scope:
  182. data.productScopeValues = formData.value.productSpuIds
  183. break
  184. case PromotionProductScopeEnum.CATEGORY.scope:
  185. data.productScopeValues = Array.isArray(formData.value.productCategoryIds)
  186. ? formData.value.productCategoryIds
  187. : [formData.value.productCategoryIds]
  188. break
  189. default:
  190. break
  191. }
  192. }
  193. </script>