SpuAndSkuList.vue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <template>
  2. <el-table :data="spuData" :expand-row-keys="expandRowKeys" row-key="id">
  3. <el-table-column type="expand" width="30">
  4. <template #default="{ row }">
  5. <SkuList
  6. ref="skuListRef"
  7. :is-activity-component="true"
  8. :prop-form-data="spuPropertyList.find((item) => item.spuId === row.id)?.spuDetail"
  9. :property-list="spuPropertyList.find((item) => item.spuId === row.id)?.propertyList"
  10. :rule-config="ruleConfig"
  11. >
  12. <template #extension>
  13. <slot></slot>
  14. </template>
  15. </SkuList>
  16. </template>
  17. </el-table-column>
  18. <el-table-column key="id" align="center" label="商品编号" prop="id" />
  19. <el-table-column label="商品图" min-width="80">
  20. <template #default="{ row }">
  21. <el-image :src="row.picUrl" class="h-30px w-30px" @click="imagePreview(row.picUrl)" />
  22. </template>
  23. </el-table-column>
  24. <el-table-column :show-overflow-tooltip="true" label="商品名称" min-width="300" prop="name" />
  25. <el-table-column align="center" label="商品售价" min-width="90" prop="price">
  26. <template #default="{ row }">
  27. {{ formatToFraction(row.price) }}
  28. </template>
  29. </el-table-column>
  30. <el-table-column align="center" label="销量" min-width="90" prop="salesCount" />
  31. <el-table-column align="center" label="库存" min-width="90" prop="stock" />
  32. <el-table-column
  33. v-if="spuData.length > 1 && deletable"
  34. align="center"
  35. label="操作"
  36. min-width="90"
  37. >
  38. <template #default="scope">
  39. <el-button link type="primary" @click="deleteSpu(scope.row.id)"> 删除</el-button>
  40. </template>
  41. </el-table-column>
  42. </el-table>
  43. </template>
  44. <script generic="T extends Spu" lang="ts" setup>
  45. import { formatToFraction } from '@/utils'
  46. import { createImageViewer } from '@/components/ImageViewer'
  47. import { Spu } from '@/api/mall/product/spu'
  48. import { RuleConfig, SkuList } from '@/views/mall/product/spu/components'
  49. import { SpuProperty } from '@/views/mall/promotion/components/index'
  50. defineOptions({ name: 'PromotionSpuAndSkuList' })
  51. const message = useMessage() // 消息弹窗
  52. const props = defineProps<{
  53. spuList: T[]
  54. ruleConfig: RuleConfig[]
  55. spuPropertyListP: SpuProperty<T>[]
  56. deletable?: boolean // SPU 是否可删除;
  57. }>()
  58. const spuData = ref<Spu[]>([]) // spu 详情数据列表
  59. const skuListRef = ref() // 商品属性列表Ref
  60. const spuPropertyList = ref<SpuProperty<T>[]>([]) // spuId 对应的 sku 的属性列表
  61. const expandRowKeys = ref<string[]>([]) // 控制展开行需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。
  62. /**
  63. * 获取所有 sku 活动配置
  64. *
  65. * @param extendedAttribute 在 sku 上扩展的属性,例:秒杀活动 sku 扩展属性 productConfig 请参考 seckillActivity.ts
  66. */
  67. const getSkuConfigs = (extendedAttribute: string) => {
  68. skuListRef.value.validateSku()
  69. const seckillProducts: any[] = []
  70. spuPropertyList.value.forEach((item) => {
  71. item.spuDetail.skus?.forEach((sku: any) => {
  72. seckillProducts.push(sku[extendedAttribute] as any)
  73. })
  74. })
  75. return seckillProducts
  76. }
  77. // 暴露出给表单提交时使用
  78. defineExpose({ getSkuConfigs })
  79. /** 商品图预览 */
  80. const imagePreview = (imgUrl: string) => {
  81. createImageViewer({
  82. zIndex: 99999999,
  83. urlList: [imgUrl]
  84. })
  85. }
  86. // 删除时的触发事件
  87. const emits = defineEmits<{
  88. (e: 'delete', spuId: number): void
  89. }>()
  90. /** 多选时可以删除 SPU **/
  91. const deleteSpu = async (spuId: number) => {
  92. await message.confirm('是否删除商品编号为' + spuId + '的数据?')
  93. const index = spuData.value.findIndex((item) => item.id == spuId)
  94. spuData.value.splice(index, 1)
  95. emits('delete', spuId)
  96. }
  97. /**
  98. * 将传进来的值赋值给 skuList
  99. */
  100. watch(
  101. () => props.spuList,
  102. (data) => {
  103. if (!data) return
  104. spuData.value = data as Spu[]
  105. },
  106. {
  107. deep: true,
  108. immediate: true
  109. }
  110. )
  111. /**
  112. * 将传进来的值赋值给 skuList
  113. */
  114. watch(
  115. () => props.spuPropertyListP,
  116. (data) => {
  117. if (!data) return
  118. spuPropertyList.value = data as SpuProperty<T>[] as any
  119. // 解决如果之前选择的是单规格 spu 的话后面选择多规格 sku 多规格属性信息不展示的问题。解决方法:让 SkuList 组件重新渲染(行折叠会干掉包含的组件展开时会重新加载)
  120. setTimeout(() => {
  121. expandRowKeys.value = data.map((item) => item.spuId + '')
  122. }, 200)
  123. },
  124. {
  125. deep: true,
  126. immediate: true
  127. }
  128. )
  129. </script>