BargainActivityForm.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <template>
  2. <Dialog v-model="dialogVisible" :title="dialogTitle" width="65%">
  3. <Form
  4. ref="formRef"
  5. v-loading="formLoading"
  6. :is-col="true"
  7. :rules="rules"
  8. :schema="allSchemas.formSchema"
  9. class="mt-10px"
  10. >
  11. <template #spuId>
  12. <el-button @click="spuSelectRef.open()">选择商品</el-button>
  13. <SpuAndSkuList
  14. ref="spuAndSkuListRef"
  15. :rule-config="ruleConfig"
  16. :spu-list="spuList"
  17. :spu-property-list-p="spuPropertyList"
  18. >
  19. <el-table-column align="center" label="砍价起始价格(元)" min-width="168">
  20. <template #default="{ row: sku }">
  21. <el-input-number
  22. v-model="sku.productConfig.bargainFirstPrice"
  23. :min="0"
  24. :precision="2"
  25. :step="0.1"
  26. class="w-100%"
  27. />
  28. </template>
  29. </el-table-column>
  30. <el-table-column align="center" label="砍价底价(元)" min-width="168">
  31. <template #default="{ row: sku }">
  32. <el-input-number
  33. v-model="sku.productConfig.bargainMinPrice"
  34. :min="0"
  35. :precision="2"
  36. :step="0.1"
  37. class="w-100%"
  38. />
  39. </template>
  40. </el-table-column>
  41. <el-table-column align="center" label="活动库存" min-width="168">
  42. <template #default="{ row: sku }">
  43. <el-input-number v-model="sku.productConfig.stock" class="w-100%" />
  44. </template>
  45. </el-table-column>
  46. </SpuAndSkuList>
  47. </template>
  48. </Form>
  49. <template #footer>
  50. <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
  51. <el-button @click="dialogVisible = false">取 消</el-button>
  52. </template>
  53. </Dialog>
  54. <SpuSelect ref="spuSelectRef" :isSelectSku="true" :radio="true" @confirm="selectSpu" />
  55. </template>
  56. <script lang="ts" setup>
  57. import * as BargainActivityApi from '@/api/mall/promotion/bargain/bargainActivity'
  58. import { BargainProductVO } from '@/api/mall/promotion/bargain/bargainActivity'
  59. import { allSchemas, rules } from './bargainActivity.data'
  60. import { SpuAndSkuList, SpuProperty, SpuSelect } from '@/views/mall/promotion/components'
  61. import { getPropertyList, RuleConfig } from '@/views/mall/product/spu/components'
  62. import * as ProductSpuApi from '@/api/mall/product/spu'
  63. import { convertToInteger, formatToFraction } from '@/utils'
  64. import { cloneDeep } from 'lodash-es'
  65. defineOptions({ name: 'PromotionBargainActivityForm' })
  66. const { t } = useI18n() // 国际化
  67. const message = useMessage() // 消息弹窗
  68. const dialogVisible = ref(false) // 弹窗的是否展示
  69. const dialogTitle = ref('') // 弹窗的标题
  70. const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
  71. const formType = ref('') // 表单的类型:create - 新增;update - 修改
  72. const formRef = ref() // 表单 Ref
  73. // ================= 商品选择相关 =================
  74. const spuSelectRef = ref() // 商品和属性选择 Ref
  75. const spuAndSkuListRef = ref() // sku 秒杀配置组件Ref
  76. const spuList = ref<BargainActivityApi.SpuExtension[]>([]) // 选择的 spu
  77. const spuPropertyList = ref<SpuProperty<BargainActivityApi.SpuExtension>[]>([])
  78. const ruleConfig: RuleConfig[] = [
  79. {
  80. name: 'productConfig.bargainFirstPrice',
  81. rule: (arg) => arg > 0,
  82. message: '商品砍价起始价格不能小于 0 !!!'
  83. },
  84. {
  85. name: 'productConfig.bargainMinPrice',
  86. rule: (arg) => arg >= 0,
  87. message: '商品砍价底价不能小于 0 !!!'
  88. },
  89. {
  90. name: 'productConfig.stock',
  91. rule: (arg) => arg >= 1,
  92. message: '商品活动库存不能小于 1 !!!'
  93. }
  94. ]
  95. const selectSpu = (spuId: number, skuIds: number[]) => {
  96. formRef.value.setValues({ spuId })
  97. getSpuDetails(spuId, skuIds)
  98. }
  99. /**
  100. * 获取 SPU 详情
  101. */
  102. const getSpuDetails = async (
  103. spuId: number,
  104. skuIds: number[] | undefined,
  105. products?: BargainProductVO[]
  106. ) => {
  107. const spuProperties: SpuProperty<BargainActivityApi.SpuExtension>[] = []
  108. const res = (await ProductSpuApi.getSpuDetailList([spuId])) as BargainActivityApi.SpuExtension[]
  109. if (res.length == 0) {
  110. return
  111. }
  112. spuList.value = []
  113. // 因为只能选择一个
  114. const spu = res[0]
  115. const selectSkus =
  116. typeof skuIds === 'undefined' ? spu?.skus : spu?.skus?.filter((sku) => skuIds.includes(sku.id!))
  117. selectSkus?.forEach((sku) => {
  118. let config: BargainProductVO = {
  119. spuId: spu.id!,
  120. skuId: sku.id!,
  121. bargainFirstPrice: 1,
  122. bargainMinPrice: 1,
  123. stock: 1
  124. }
  125. if (typeof products !== 'undefined') {
  126. const product = products.find((item) => item.skuId === sku.id)
  127. if (product) {
  128. product.bargainFirstPrice = formatToFraction(product.bargainFirstPrice)
  129. product.bargainMinPrice = formatToFraction(product.bargainMinPrice)
  130. }
  131. config = product || config
  132. }
  133. sku.productConfig = config
  134. })
  135. spu.skus = selectSkus as BargainActivityApi.SkuExtension[]
  136. spuProperties.push({
  137. spuId: spu.id!,
  138. spuDetail: spu,
  139. propertyList: getPropertyList(spu)
  140. })
  141. spuList.value.push(spu)
  142. spuPropertyList.value = spuProperties
  143. }
  144. // ================= end =================
  145. /** 打开弹窗 */
  146. const open = async (type: string, id?: number) => {
  147. dialogVisible.value = true
  148. dialogTitle.value = t('action.' + type)
  149. formType.value = type
  150. await resetForm()
  151. // 修改时,设置数据
  152. if (id) {
  153. formLoading.value = true
  154. try {
  155. const data = (await BargainActivityApi.getBargainActivity(
  156. id
  157. )) as BargainActivityApi.BargainActivityVO
  158. // 用户每次砍价金额分转元, 分转元
  159. data.randomMinPrice = formatToFraction(data.randomMinPrice)
  160. data.randomMaxPrice = formatToFraction(data.randomMaxPrice)
  161. // 对齐活动商品处理结构
  162. await getSpuDetails(
  163. data.spuId!,
  164. [data.skuId],
  165. [
  166. {
  167. spuId: data.spuId!,
  168. skuId: data.skuId,
  169. bargainFirstPrice: data.bargainFirstPrice, // 砍价起始价格,单位分
  170. bargainMinPrice: data.bargainMinPrice, // 砍价底价
  171. stock: data.stock // 活动库存
  172. }
  173. ]
  174. )
  175. formRef.value.setValues(data)
  176. } finally {
  177. formLoading.value = false
  178. }
  179. }
  180. }
  181. defineExpose({ open }) // 提供 open 方法,用于打开弹窗
  182. /** 重置表单 */
  183. const resetForm = async () => {
  184. spuList.value = []
  185. spuPropertyList.value = []
  186. await nextTick()
  187. formRef.value.getElFormRef().resetFields()
  188. }
  189. /** 提交表单 */
  190. const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
  191. const submitForm = async () => {
  192. // 校验表单
  193. if (!formRef) return
  194. const valid = await formRef.value.getElFormRef().validate()
  195. if (!valid) return
  196. // 提交请求
  197. formLoading.value = true
  198. try {
  199. const data = cloneDeep(formRef.value.formModel) as BargainActivityApi.BargainActivityVO
  200. const products = spuAndSkuListRef.value.getSkuConfigs('productConfig')
  201. products.forEach((item: BargainProductVO) => {
  202. // 砍价价格元转分
  203. item.bargainFirstPrice = convertToInteger(item.bargainFirstPrice)
  204. item.bargainMinPrice = convertToInteger(item.bargainMinPrice)
  205. })
  206. // 用户每次砍价金额分转元, 元转分
  207. data.randomMinPrice = convertToInteger(data.randomMinPrice)
  208. data.randomMaxPrice = convertToInteger(data.randomMaxPrice)
  209. const formData = { ...data, ...products[0] }
  210. if (formType.value === 'create') {
  211. await BargainActivityApi.createBargainActivity(formData)
  212. message.success(t('common.createSuccess'))
  213. } else {
  214. await BargainActivityApi.updateBargainActivity(formData)
  215. message.success(t('common.updateSuccess'))
  216. }
  217. dialogVisible.value = false
  218. // 发送操作成功的事件
  219. emit('success')
  220. } finally {
  221. formLoading.value = false
  222. }
  223. }
  224. </script>